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:
Mazdak Farrokhzad 2019-06-19 01:52:09 +02:00 committed by GitHub
commit dcd5b20177
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 53 deletions

View file

@ -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());

View file

@ -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
}
}

View 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`.

View 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() {}

View 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`.

View 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() {}

View 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`.