Skip to content

Commit 7f58193

Browse files
committed
mGCA: Render traits dyn incompatible if the ty of an assoc const refs Self (barring Self projections)
1 parent 618c15e commit 7f58193

9 files changed

Lines changed: 292 additions & 118 deletions

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
5858
let mut user_written_bounds = Vec::new();
5959
let mut potential_assoc_items = Vec::new();
6060
for poly_trait_ref in hir_bounds.iter() {
61+
// FIXME(mgca): We actually leak `trait_object_dummy_self` if the type of any assoc
62+
// const mentions `Self` (in "Self projections" which we intentionally
63+
// allow). That's because we query feed the instantiated type to `type_of`.
64+
// That's really bad, dummy self should never escape lowering! It leads us
65+
// to accept less code we'd like to support and can lead to ICEs later.
6166
let result = self.lower_poly_trait_ref(
6267
poly_trait_ref,
6368
dummy_self,

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 79 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -761,12 +761,12 @@ pub struct ImplSourceUserDefinedData<'tcx, N> {
761761

762762
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
763763
pub enum DynCompatibilityViolation {
764-
/// `Self: Sized` declared on the trait.
765-
SizedSelf(SmallVec<[Span; 1]>),
766-
767764
/// Trait is marked `#[rustc_dyn_incompatible_trait]`.
768765
ExplicitlyDynIncompatible(SmallVec<[Span; 1]>),
769766

767+
/// `Self: Sized` declared on the trait.
768+
SizedSelf(SmallVec<[Span; 1]>),
769+
770770
/// Supertrait reference references `Self` an in illegal location
771771
/// (e.g., `trait Foo : Bar<Self>`).
772772
SupertraitSelf(SmallVec<[Span; 1]>),
@@ -778,130 +778,105 @@ pub enum DynCompatibilityViolation {
778778
SupertraitConst(SmallVec<[Span; 1]>),
779779

780780
/// Method has something illegal.
781-
Method(Symbol, MethodViolationCode, Span),
782-
783-
/// Associated constant.
784-
AssocConst(Symbol, Span),
785-
786-
/// Generic associated constant.
787-
GenericAssocConst(Symbol, Span),
781+
Method(Symbol, MethodViolation, Span),
788782

789-
/// Associated constant that wasn't marked `#[type_const]`.
790-
NonTypeAssocConst(Symbol, Span),
783+
/// Associated constant is faulty.
784+
AssocConst(Symbol, AssocConstViolation, Span),
791785

792-
/// Generic associated type.
786+
/// Generic associated type (GAT).
793787
GenericAssocTy(Symbol, Span),
794788
}
795789

796790
impl DynCompatibilityViolation {
797791
pub fn error_msg(&self) -> Cow<'static, str> {
792+
// FIXME(mgca): For method violations we just say "method ..." but for assoc const ones we
793+
// say "it contains ... associated constant ...". Make it consistent.
794+
798795
match self {
799-
DynCompatibilityViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
800-
DynCompatibilityViolation::ExplicitlyDynIncompatible(_) => {
801-
"it opted out of dyn-compatibility".into()
802-
}
803-
DynCompatibilityViolation::SupertraitSelf(spans) => {
796+
Self::ExplicitlyDynIncompatible(_) => "it opted out of dyn-compatibility".into(),
797+
Self::SizedSelf(_) => "it requires `Self: Sized`".into(),
798+
Self::SupertraitSelf(spans) => {
804799
if spans.iter().any(|sp| *sp != DUMMY_SP) {
805800
"it uses `Self` as a type parameter".into()
806801
} else {
807802
"it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
808803
.into()
809804
}
810805
}
811-
DynCompatibilityViolation::SupertraitNonLifetimeBinder(_) => {
806+
Self::SupertraitNonLifetimeBinder(_) => {
812807
"where clause cannot reference non-lifetime `for<...>` variables".into()
813808
}
814-
DynCompatibilityViolation::SupertraitConst(_) => {
815-
"it cannot have a `const` supertrait".into()
816-
}
817-
DynCompatibilityViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
809+
Self::SupertraitConst(_) => "it cannot have a `const` supertrait".into(),
810+
Self::Method(name, MethodViolation::StaticMethod(_), _) => {
818811
format!("associated function `{name}` has no `self` parameter").into()
819812
}
820-
DynCompatibilityViolation::Method(
821-
name,
822-
MethodViolationCode::ReferencesSelfInput(_),
823-
DUMMY_SP,
824-
) => format!("method `{name}` references the `Self` type in its parameters").into(),
825-
DynCompatibilityViolation::Method(
826-
name,
827-
MethodViolationCode::ReferencesSelfInput(_),
828-
_,
829-
) => format!("method `{name}` references the `Self` type in this parameter").into(),
830-
DynCompatibilityViolation::Method(
831-
name,
832-
MethodViolationCode::ReferencesSelfOutput,
833-
_,
834-
) => format!("method `{name}` references the `Self` type in its return type").into(),
835-
DynCompatibilityViolation::Method(
836-
name,
837-
MethodViolationCode::ReferencesImplTraitInTrait(_),
838-
_,
839-
) => {
813+
Self::Method(name, MethodViolation::ReferencesSelfInput(_), DUMMY_SP) => {
814+
format!("method `{name}` references the `Self` type in its parameters").into()
815+
}
816+
Self::Method(name, MethodViolation::ReferencesSelfInput(_), _) => {
817+
format!("method `{name}` references the `Self` type in this parameter").into()
818+
}
819+
Self::Method(name, MethodViolation::ReferencesSelfOutput, _) => {
820+
format!("method `{name}` references the `Self` type in its return type").into()
821+
}
822+
Self::Method(name, MethodViolation::ReferencesImplTraitInTrait(_), _) => {
840823
format!("method `{name}` references an `impl Trait` type in its return type").into()
841824
}
842-
DynCompatibilityViolation::Method(name, MethodViolationCode::AsyncFn, _) => {
825+
Self::Method(name, MethodViolation::AsyncFn, _) => {
843826
format!("method `{name}` is `async`").into()
844827
}
845-
DynCompatibilityViolation::Method(name, MethodViolationCode::CVariadic, _) => {
828+
Self::Method(name, MethodViolation::CVariadic, _) => {
846829
format!("method `{name}` is C-variadic").into()
847830
}
848-
DynCompatibilityViolation::Method(
849-
name,
850-
MethodViolationCode::WhereClauseReferencesSelf,
851-
_,
852-
) => format!("method `{name}` references the `Self` type in its `where` clause").into(),
853-
DynCompatibilityViolation::Method(name, MethodViolationCode::Generic, _) => {
831+
Self::Method(name, MethodViolation::WhereClauseReferencesSelf, _) => {
832+
format!("method `{name}` references the `Self` type in its `where` clause").into()
833+
}
834+
Self::Method(name, MethodViolation::Generic, _) => {
854835
format!("method `{name}` has generic type parameters").into()
855836
}
856-
DynCompatibilityViolation::Method(
857-
name,
858-
MethodViolationCode::UndispatchableReceiver(_),
859-
_,
860-
) => format!("method `{name}`'s `self` parameter cannot be dispatched on").into(),
861-
DynCompatibilityViolation::AssocConst(name, _) => {
837+
Self::Method(name, MethodViolation::UndispatchableReceiver(_), _) => {
838+
format!("method `{name}`'s `self` parameter cannot be dispatched on").into()
839+
}
840+
Self::AssocConst(name, AssocConstViolation::FeatureNotEnabled, _) => {
862841
format!("it contains associated const `{name}`").into()
863842
}
864-
DynCompatibilityViolation::GenericAssocConst(name, _) => {
843+
Self::AssocConst(name, AssocConstViolation::Generic, _) => {
865844
format!("it contains generic associated const `{name}`").into()
866845
}
867-
DynCompatibilityViolation::NonTypeAssocConst(name, _) => {
846+
Self::AssocConst(name, AssocConstViolation::NonType, _) => {
868847
format!("it contains associated const `{name}` that's not marked `#[type_const]`")
869848
.into()
870849
}
871-
DynCompatibilityViolation::GenericAssocTy(name, _) => {
850+
Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!(
851+
"it contains associated const `{name}` whose type references the `Self` type"
852+
)
853+
.into(),
854+
Self::GenericAssocTy(name, _) => {
872855
format!("it contains generic associated type `{name}`").into()
873856
}
874857
}
875858
}
876859

877860
pub fn solution(&self) -> DynCompatibilityViolationSolution {
878861
match self {
879-
DynCompatibilityViolation::SizedSelf(_)
880-
| DynCompatibilityViolation::ExplicitlyDynIncompatible(_)
881-
| DynCompatibilityViolation::SupertraitSelf(_)
882-
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(..)
883-
| DynCompatibilityViolation::SupertraitConst(_) => {
884-
DynCompatibilityViolationSolution::None
885-
}
886-
DynCompatibilityViolation::Method(
862+
Self::ExplicitlyDynIncompatible(_)
863+
| Self::SizedSelf(_)
864+
| Self::SupertraitSelf(_)
865+
| Self::SupertraitNonLifetimeBinder(..)
866+
| Self::SupertraitConst(_) => DynCompatibilityViolationSolution::None,
867+
Self::Method(
887868
name,
888-
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
869+
MethodViolation::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
889870
_,
890871
) => DynCompatibilityViolationSolution::AddSelfOrMakeSized {
891872
name: *name,
892873
add_self_sugg: add_self_sugg.clone(),
893874
make_sized_sugg: make_sized_sugg.clone(),
894875
},
895-
DynCompatibilityViolation::Method(
896-
name,
897-
MethodViolationCode::UndispatchableReceiver(Some(span)),
898-
_,
899-
) => DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span),
900-
DynCompatibilityViolation::AssocConst(name, _)
901-
| DynCompatibilityViolation::GenericAssocConst(name, _)
902-
| DynCompatibilityViolation::NonTypeAssocConst(name, _)
903-
| DynCompatibilityViolation::GenericAssocTy(name, _)
904-
| DynCompatibilityViolation::Method(name, ..) => {
876+
Self::Method(name, MethodViolation::UndispatchableReceiver(Some(span)), _) => {
877+
DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span)
878+
}
879+
Self::Method(name, ..) | Self::AssocConst(name, ..) | Self::GenericAssocTy(name, _) => {
905880
DynCompatibilityViolationSolution::MoveToAnotherTrait(*name)
906881
}
907882
}
@@ -911,16 +886,14 @@ impl DynCompatibilityViolation {
911886
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
912887
// diagnostics use a `note` instead of a `span_label`.
913888
match self {
914-
DynCompatibilityViolation::SupertraitSelf(spans)
915-
| DynCompatibilityViolation::SizedSelf(spans)
916-
| DynCompatibilityViolation::ExplicitlyDynIncompatible(spans)
917-
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)
918-
| DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(),
919-
DynCompatibilityViolation::AssocConst(_, span)
920-
| DynCompatibilityViolation::GenericAssocConst(_, span)
921-
| DynCompatibilityViolation::NonTypeAssocConst(_, span)
922-
| DynCompatibilityViolation::GenericAssocTy(_, span)
923-
| DynCompatibilityViolation::Method(_, _, span) => {
889+
Self::ExplicitlyDynIncompatible(spans)
890+
| Self::SizedSelf(spans)
891+
| Self::SupertraitSelf(spans)
892+
| Self::SupertraitNonLifetimeBinder(spans)
893+
| Self::SupertraitConst(spans) => spans.clone(),
894+
Self::Method(_, _, span)
895+
| Self::AssocConst(_, _, span)
896+
| Self::GenericAssocTy(_, span) => {
924897
if *span != DUMMY_SP {
925898
smallvec![*span]
926899
} else {
@@ -987,7 +960,7 @@ impl DynCompatibilityViolationSolution {
987960

988961
/// Reasons a method might not be dyn-compatible.
989962
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
990-
pub enum MethodViolationCode {
963+
pub enum MethodViolation {
991964
/// e.g., `fn foo()`
992965
StaticMethod(Option<(/* add &self */ (String, Span), /* add Self: Sized */ (String, Span))>),
993966

@@ -1016,6 +989,22 @@ pub enum MethodViolationCode {
1016989
UndispatchableReceiver(Option<Span>),
1017990
}
1018991

992+
/// Reasons an associated const might not be dyn compatible.
993+
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
994+
pub enum AssocConstViolation {
995+
/// Unstable feature `min_generic_const_args` wasn't enabled.
996+
FeatureNotEnabled,
997+
998+
/// Has own generic parameters (GAC).
999+
Generic,
1000+
1001+
/// Isn't marked `#[type_const]`.
1002+
NonType,
1003+
1004+
/// Its type mentions the `Self` type parameter.
1005+
TypeReferencesSelf,
1006+
}
1007+
10191008
/// These are the error cases for `codegen_select_candidate`.
10201009
#[derive(Copy, Clone, Debug, Hash, HashStable, Encodable, Decodable)]
10211010
pub enum CodegenObligationError {

0 commit comments

Comments
 (0)