Rollup merge of #61896 - eddyb:correct-self-ctor, r=petrochenkov
rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`. Fixes #61882. r? @petrochenkov cc @varkor
This commit is contained in:
commit
dcd5b20177
7 changed files with 109 additions and 53 deletions
|
@ -3957,52 +3957,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
|
||||
}
|
||||
|
||||
// Rewrite `SelfCtor` to `Ctor`
|
||||
pub fn rewrite_self_ctor(
|
||||
&self,
|
||||
res: Res,
|
||||
span: Span,
|
||||
) -> Result<Res, ErrorReported> {
|
||||
let tcx = self.tcx;
|
||||
if let Res::SelfCtor(impl_def_id) = res {
|
||||
let ty = self.impl_self_ty(span, impl_def_id).ty;
|
||||
let adt_def = ty.ty_adt_def();
|
||||
|
||||
match adt_def {
|
||||
Some(adt_def) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
let ctor_def_id = variant.ctor_def_id.unwrap();
|
||||
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
|
||||
}
|
||||
_ => {
|
||||
let mut err = tcx.sess.struct_span_err(span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs");
|
||||
if let Some(adt_def) = adt_def {
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Enum => {
|
||||
err.help("did you mean to use one of the enum's variants?");
|
||||
},
|
||||
AdtKind::Struct |
|
||||
AdtKind::Union => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use curly brackets",
|
||||
String::from("Self { /* fields */ }"),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
Err(ErrorReported)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiates the given path, which must refer to an item with the given
|
||||
// number of type parameters and type.
|
||||
pub fn instantiate_value_path(&self,
|
||||
|
@ -4022,12 +3976,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let tcx = self.tcx;
|
||||
|
||||
let res = match self.rewrite_self_ctor(res, span) {
|
||||
Ok(res) => res,
|
||||
Err(ErrorReported) => return (tcx.types.err, res),
|
||||
};
|
||||
let path_segs = match res {
|
||||
Res::Local(_) => vec![],
|
||||
Res::Local(_) | Res::SelfCtor(_) => vec![],
|
||||
Res::Def(kind, def_id) =>
|
||||
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
|
||||
_ => bug!("instantiate_value_path on {:?}", res),
|
||||
|
@ -4132,13 +4082,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
tcx.generics_of(*def_id).has_self
|
||||
}).unwrap_or(false);
|
||||
|
||||
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
|
||||
let ty = self.impl_self_ty(span, impl_def_id).ty;
|
||||
let adt_def = ty.ty_adt_def();
|
||||
|
||||
match ty.sty {
|
||||
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
let ctor_def_id = variant.ctor_def_id.unwrap();
|
||||
(
|
||||
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
|
||||
Some(substs),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let mut err = tcx.sess.struct_span_err(span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs");
|
||||
if let Some(adt_def) = adt_def {
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Enum => {
|
||||
err.help("did you mean to use one of the enum's variants?");
|
||||
},
|
||||
AdtKind::Struct |
|
||||
AdtKind::Union => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use curly brackets",
|
||||
String::from("Self { /* fields */ }"),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
return (tcx.types.err, res)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(res, None)
|
||||
};
|
||||
let def_id = res.def_id();
|
||||
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let ty = tcx.type_of(def_id);
|
||||
|
||||
let substs = AstConv::create_substs_for_generic_args(
|
||||
let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args(
|
||||
tcx,
|
||||
def_id,
|
||||
&[][..],
|
||||
|
@ -4208,7 +4198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
));
|
||||
assert!(!substs.has_escaping_bound_vars());
|
||||
assert!(!ty.has_escaping_bound_vars());
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ pub struct Gcm<E>(E);
|
|||
impl<E> Gcm<E> {
|
||||
pub fn crash(e: E) -> Self {
|
||||
Self::<E>(e)
|
||||
//~^ ERROR type arguments are not allowed for this type
|
||||
}
|
||||
}
|
||||
|
9
src/test/ui/issues/issue-57924.stderr
Normal file
9
src/test/ui/issues/issue-57924.stderr
Normal file
|
@ -0,0 +1,9 @@
|
|||
error[E0109]: type arguments are not allowed for this type
|
||||
--> $DIR/issue-57924.rs:5:16
|
||||
|
|
||||
LL | Self::<E>(e)
|
||||
| ^ type argument not allowed
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0109`.
|
11
src/test/ui/issues/issue-61882-2.rs
Normal file
11
src/test/ui/issues/issue-61882-2.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
struct A<T>(T);
|
||||
|
||||
impl A<&'static u8> {
|
||||
fn f() {
|
||||
let x = 0;
|
||||
Self(&x);
|
||||
//~^ ERROR `x` does not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
15
src/test/ui/issues/issue-61882-2.stderr
Normal file
15
src/test/ui/issues/issue-61882-2.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/issue-61882-2.rs:6:14
|
||||
|
|
||||
LL | Self(&x);
|
||||
| ^^
|
||||
| |
|
||||
| borrowed value does not live long enough
|
||||
| requires that `x` is borrowed for `'static`
|
||||
LL |
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
9
src/test/ui/issues/issue-61882.rs
Normal file
9
src/test/ui/issues/issue-61882.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
struct A<T>(T);
|
||||
|
||||
impl A<bool> {
|
||||
const B: A<u8> = Self(0);
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
21
src/test/ui/issues/issue-61882.stderr
Normal file
21
src/test/ui/issues/issue-61882.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-61882.rs:4:27
|
||||
|
|
||||
LL | const B: A<u8> = Self(0);
|
||||
| ^ expected bool, found integer
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-61882.rs:4:22
|
||||
|
|
||||
LL | const B: A<u8> = Self(0);
|
||||
| ^^^^^^^ expected u8, found bool
|
||||
|
|
||||
= note: expected type `A<u8>`
|
||||
found type `A<bool>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in a new issue