Rollup merge of #105287 - compiler-errors:issue-105275, r=eholk

Synthesize substitutions for bad auto traits in dyn types

Auto traits are stored as just `DefId`s inside a `dyn Trait`'s existential predicates list. This is usually fine, since auto traits are forbidden to have generics -- but this becomes a problem for an ill-formed auto trait.

But since this will always result in an error, just synthesize some dummy (error) substitutions which are used at least to keep trait selection code happy about the number of substs in a trait ref.

Fixes #104808
This commit is contained in:
Matthias Krüger 2022-12-06 13:27:43 +01:00 committed by GitHub
commit 0a07ffe4ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 2 deletions

View File

@ -101,6 +101,20 @@ impl GenericParamDef {
_ => None,
}
}
pub fn to_error<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
preceding_substs: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
match &self.kind {
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
ty::GenericParamDefKind::Const { .. } => {
tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
}
}
}
}
#[derive(Default)]

View File

@ -722,8 +722,17 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
}
ExistentialPredicate::AutoTrait(did) => {
let trait_ref = self.rebind(tcx.mk_trait_ref(did, [self_ty]));
trait_ref.without_const().to_predicate(tcx)
let generics = tcx.generics_of(did);
let trait_ref = if generics.params.len() == 1 {
tcx.mk_trait_ref(did, [self_ty])
} else {
// If this is an ill-formed auto trait, then synthesize
// new error substs for the missing generics.
let err_substs =
ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]);
tcx.mk_trait_ref(did, err_substs)
};
self.rebind(trait_ref).without_const().to_predicate(tcx)
}
}
}

View File

@ -352,6 +352,22 @@ impl<'tcx> InternalSubsts<'tcx> {
}
}
// Extend an `original_substs` list to the full number of substs expected by `def_id`,
// filling in the missing parameters with error ty/ct or 'static regions.
pub fn extend_with_error(
tcx: TyCtxt<'tcx>,
def_id: DefId,
original_substs: &[GenericArg<'tcx>],
) -> SubstsRef<'tcx> {
ty::InternalSubsts::for_item(tcx, def_id, |def, substs| {
if let Some(subst) = original_substs.get(def.index as usize) {
*subst
} else {
def.to_error(tcx, substs)
}
})
}
#[inline]
pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
self.iter()

View File

@ -0,0 +1,11 @@
#![feature(auto_traits)]
auto trait Trait1<'a> {}
//~^ ERROR auto traits cannot have generic parameters
fn f<'a>(x: &dyn Trait1<'a>)
{}
fn main() {
f(&1);
}

View File

@ -0,0 +1,11 @@
error[E0567]: auto traits cannot have generic parameters
--> $DIR/bad-generics-on-dyn.rs:3:18
|
LL | auto trait Trait1<'a> {}
| ------^^^^ help: remove the parameters
| |
| auto trait cannot have generic parameters
error: aborting due to previous error
For more information about this error, try `rustc --explain E0567`.