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)))
|
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
|
// Instantiates the given path, which must refer to an item with the given
|
||||||
// number of type parameters and type.
|
// number of type parameters and type.
|
||||||
pub fn instantiate_value_path(&self,
|
pub fn instantiate_value_path(&self,
|
||||||
|
@ -4022,12 +3976,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
let tcx = self.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 {
|
let path_segs = match res {
|
||||||
Res::Local(_) => vec![],
|
Res::Local(_) | Res::SelfCtor(_) => vec![],
|
||||||
Res::Def(kind, def_id) =>
|
Res::Def(kind, def_id) =>
|
||||||
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
|
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
|
||||||
_ => bug!("instantiate_value_path on {:?}", res),
|
_ => bug!("instantiate_value_path on {:?}", res),
|
||||||
|
@ -4132,13 +4082,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
tcx.generics_of(*def_id).has_self
|
tcx.generics_of(*def_id).has_self
|
||||||
}).unwrap_or(false);
|
}).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();
|
let def_id = res.def_id();
|
||||||
|
|
||||||
// The things we are substituting into the type should not contain
|
// The things we are substituting into the type should not contain
|
||||||
// escaping late-bound regions, and nor should the base type scheme.
|
// escaping late-bound regions, and nor should the base type scheme.
|
||||||
let ty = tcx.type_of(def_id);
|
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,
|
tcx,
|
||||||
def_id,
|
def_id,
|
||||||
&[][..],
|
&[][..],
|
||||||
|
@ -4208,7 +4198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
));
|
||||||
assert!(!substs.has_escaping_bound_vars());
|
assert!(!substs.has_escaping_bound_vars());
|
||||||
assert!(!ty.has_escaping_bound_vars());
|
assert!(!ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ pub struct Gcm<E>(E);
|
||||||
impl<E> Gcm<E> {
|
impl<E> Gcm<E> {
|
||||||
pub fn crash(e: E) -> Self {
|
pub fn crash(e: E) -> Self {
|
||||||
Self::<E>(e)
|
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