Resolve partially resolved paths in struct patterns/expressions
Treat Def::Err correctly in struct patterns Make instantiate_path and instantiate_type a bit closer to each other
This commit is contained in:
parent
49ea3d48a2
commit
a397b60ebb
|
@ -67,21 +67,6 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
|
|
||||||
match pat.node {
|
|
||||||
PatKind::TupleStruct(..) |
|
|
||||||
PatKind::Path(..) |
|
|
||||||
PatKind::Struct(..) => {
|
|
||||||
match dm.get(&pat.id).map(|d| d.full_def()) {
|
|
||||||
Some(Def::Variant(..)) | Some(Def::Struct(..)) |
|
|
||||||
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
|
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||||
|
|
|
@ -489,39 +489,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
|
fn check_pat_struct(&self,
|
||||||
path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
|
pat: &'gcx hir::Pat,
|
||||||
etc: bool, expected: Ty<'tcx>) {
|
path: &hir::Path,
|
||||||
let tcx = self.tcx;
|
fields: &'gcx [Spanned<hir::FieldPat>],
|
||||||
|
etc: bool,
|
||||||
let def = tcx.expect_def(pat.id);
|
expected: Ty<'tcx>)
|
||||||
let variant = match self.def_struct_variant(def, path.span) {
|
{
|
||||||
Some((_, variant)) => variant,
|
// Resolve the path and check the definition for errors.
|
||||||
None => {
|
let def = self.finish_resolving_struct_path(path, pat.id, pat.span);
|
||||||
let name = pprust::path_to_string(path);
|
let variant = if let Some(variant) = self.check_struct_path(def, path, pat.span) {
|
||||||
span_err!(tcx.sess, pat.span, E0163,
|
variant
|
||||||
"`{}` does not name a struct or a struct variant", name);
|
} else {
|
||||||
self.write_error(pat.id);
|
self.write_error(pat.id);
|
||||||
|
for field in fields {
|
||||||
for field in fields {
|
self.check_pat(&field.node.pat, self.tcx.types.err);
|
||||||
self.check_pat(&field.node.pat, tcx.types.err);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let pat_ty = self.instantiate_type(def.def_id(), path);
|
// Type check the path.
|
||||||
let item_substs = match pat_ty.sty {
|
let pat_ty = self.instantiate_type_path(def.def_id(), path, pat.id);
|
||||||
|
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||||
|
|
||||||
|
// Type check subpatterns.
|
||||||
|
let substs = match pat_ty.sty {
|
||||||
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
|
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
|
||||||
_ => span_bug!(pat.span, "struct variant is not an ADT")
|
_ => span_bug!(pat.span, "struct variant is not an ADT")
|
||||||
};
|
};
|
||||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
self.check_struct_pat_fields(pat.span, fields, variant, substs, etc);
|
||||||
self.check_struct_pat_fields(pat.span, fields, variant, &item_substs, etc);
|
|
||||||
|
|
||||||
self.write_ty(pat.id, pat_ty);
|
|
||||||
self.write_substs(pat.id, ty::ItemSubsts {
|
|
||||||
substs: item_substs
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat_path(&self,
|
fn check_pat_path(&self,
|
||||||
|
@ -539,8 +535,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolve the path and check the definition for errors.
|
// Resolve the path and check the definition for errors.
|
||||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id),
|
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
|
||||||
opt_self_ty, path, pat.span, pat.id);
|
pat.id, pat.span);
|
||||||
match def {
|
match def {
|
||||||
Def::Err => {
|
Def::Err => {
|
||||||
self.set_tainted_by_errors();
|
self.set_tainted_by_errors();
|
||||||
|
@ -565,8 +561,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// Type check the path.
|
// Type check the path.
|
||||||
let scheme = tcx.lookup_item_type(def.def_id());
|
let scheme = tcx.lookup_item_type(def.def_id());
|
||||||
let predicates = tcx.lookup_predicates(def.def_id());
|
let predicates = tcx.lookup_predicates(def.def_id());
|
||||||
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id);
|
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
|
||||||
let pat_ty = self.node_ty(pat.id);
|
opt_ty, def, pat.span, pat.id);
|
||||||
self.demand_suptype(pat.span, expected, pat_ty);
|
self.demand_suptype(pat.span, expected, pat_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,9 +593,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolve the path and check the definition for errors.
|
// Resolve the path and check the definition for errors.
|
||||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id),
|
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
|
||||||
None, path, pat.span, pat.id);
|
let variant = match def {
|
||||||
match def {
|
|
||||||
Def::Err => {
|
Def::Err => {
|
||||||
self.set_tainted_by_errors();
|
self.set_tainted_by_errors();
|
||||||
on_error();
|
on_error();
|
||||||
|
@ -609,10 +604,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
report_unexpected_def(false);
|
report_unexpected_def(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Def::Variant(..) | Def::Struct(..) => {} // OK
|
Def::Variant(..) | Def::Struct(..) => {
|
||||||
|
tcx.expect_variant_def(def)
|
||||||
|
}
|
||||||
_ => bug!("unexpected pattern definition {:?}", def)
|
_ => bug!("unexpected pattern definition {:?}", def)
|
||||||
}
|
};
|
||||||
let variant = tcx.expect_variant_def(def);
|
|
||||||
if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
|
if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
|
||||||
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
|
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
|
||||||
// is allowed for backward compatibility.
|
// is allowed for backward compatibility.
|
||||||
|
@ -633,20 +629,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
scheme
|
scheme
|
||||||
};
|
};
|
||||||
let predicates = tcx.lookup_predicates(def.def_id());
|
let predicates = tcx.lookup_predicates(def.def_id());
|
||||||
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id);
|
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
|
||||||
let pat_ty = self.node_ty(pat.id);
|
opt_ty, def, pat.span, pat.id);
|
||||||
self.demand_eqtype(pat.span, expected, pat_ty);
|
self.demand_eqtype(pat.span, expected, pat_ty);
|
||||||
|
|
||||||
// Type check subpatterns.
|
// Type check subpatterns.
|
||||||
if subpats.len() == variant.fields.len() ||
|
if subpats.len() == variant.fields.len() ||
|
||||||
subpats.len() < variant.fields.len() && ddpos.is_some() {
|
subpats.len() < variant.fields.len() && ddpos.is_some() {
|
||||||
let expected_substs = match pat_ty.sty {
|
let substs = match pat_ty.sty {
|
||||||
ty::TyEnum(_, expected_substs) => expected_substs,
|
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
|
||||||
ty::TyStruct(_, expected_substs) => expected_substs,
|
|
||||||
ref ty => bug!("unexpected pattern type {:?}", ty),
|
ref ty => bug!("unexpected pattern type {:?}", ty),
|
||||||
};
|
};
|
||||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
|
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
|
||||||
let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs);
|
let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
|
||||||
self.check_pat(&subpat, field_ty);
|
self.check_pat(&subpat, field_ty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1621,62 +1621,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
///
|
///
|
||||||
/// Note that this function is only intended to be used with type-paths,
|
/// Note that this function is only intended to be used with type-paths,
|
||||||
/// not with value-paths.
|
/// not with value-paths.
|
||||||
pub fn instantiate_type(&self,
|
pub fn instantiate_type_path(&self,
|
||||||
did: DefId,
|
did: DefId,
|
||||||
path: &hir::Path)
|
path: &hir::Path,
|
||||||
-> Ty<'tcx>
|
node_id: ast::NodeId)
|
||||||
{
|
-> Ty<'tcx> {
|
||||||
debug!("instantiate_type(did={:?}, path={:?})", did, path);
|
debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
|
||||||
let type_scheme =
|
let type_scheme = self.tcx.lookup_item_type(did);
|
||||||
self.tcx.lookup_item_type(did);
|
let type_predicates = self.tcx.lookup_predicates(did);
|
||||||
let type_predicates =
|
|
||||||
self.tcx.lookup_predicates(did);
|
|
||||||
let substs = AstConv::ast_path_substs_for_ty(self, self,
|
let substs = AstConv::ast_path_substs_for_ty(self, self,
|
||||||
path.span,
|
path.span,
|
||||||
PathParamMode::Optional,
|
PathParamMode::Optional,
|
||||||
&type_scheme.generics,
|
&type_scheme.generics,
|
||||||
path.segments.last().unwrap());
|
path.segments.last().unwrap());
|
||||||
debug!("instantiate_type: ty={:?} substs={:?}", &type_scheme.ty, &substs);
|
let substs = self.tcx.mk_substs(substs);
|
||||||
let bounds =
|
debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs);
|
||||||
self.instantiate_bounds(path.span, &substs, &type_predicates);
|
let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
|
||||||
self.add_obligations_for_parameters(
|
let cause = traits::ObligationCause::new(path.span, self.body_id,
|
||||||
traits::ObligationCause::new(
|
traits::ItemObligation(did));
|
||||||
path.span,
|
self.add_obligations_for_parameters(cause, &bounds);
|
||||||
self.body_id,
|
|
||||||
traits::ItemObligation(did)),
|
|
||||||
&bounds);
|
|
||||||
|
|
||||||
self.instantiate_type_scheme(path.span, &substs, &type_scheme.ty)
|
let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty);
|
||||||
}
|
self.write_ty(node_id, ty_substituted);
|
||||||
|
self.write_substs(node_id, ty::ItemSubsts {
|
||||||
/// Return the dict-like variant corresponding to a given `Def`.
|
substs: substs
|
||||||
pub fn def_struct_variant(&self,
|
});
|
||||||
def: Def,
|
ty_substituted
|
||||||
_span: Span)
|
|
||||||
-> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
|
|
||||||
{
|
|
||||||
let (adt, variant) = match def {
|
|
||||||
Def::Variant(enum_id, variant_id) => {
|
|
||||||
let adt = self.tcx.lookup_adt_def(enum_id);
|
|
||||||
(adt, adt.variant_with_id(variant_id))
|
|
||||||
}
|
|
||||||
Def::Struct(did) | Def::TyAlias(did) => {
|
|
||||||
let typ = self.tcx.lookup_item_type(did);
|
|
||||||
if let ty::TyStruct(adt, _) = typ.ty.sty {
|
|
||||||
(adt, adt.struct_variant())
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return None
|
|
||||||
};
|
|
||||||
|
|
||||||
if variant.kind == ty::VariantKind::Struct ||
|
|
||||||
variant.kind == ty::VariantKind::Unit {
|
|
||||||
Some((adt, variant))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_nil(&self, node_id: ast::NodeId) {
|
pub fn write_nil(&self, node_id: ast::NodeId) {
|
||||||
|
@ -3151,34 +3121,54 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_struct_path(&self,
|
||||||
|
def: Def,
|
||||||
|
path: &hir::Path,
|
||||||
|
span: Span)
|
||||||
|
-> Option<ty::VariantDef<'tcx>> {
|
||||||
|
let variant = match def {
|
||||||
|
Def::Err => {
|
||||||
|
self.set_tainted_by_errors();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Def::Variant(..) | Def::Struct(..) => {
|
||||||
|
Some(self.tcx.expect_variant_def(def))
|
||||||
|
}
|
||||||
|
Def::TyAlias(did) | Def::AssociatedTy(_, did) => {
|
||||||
|
if let ty::TyStruct(adt, _) = self.tcx.lookup_item_type(did).ty.sty {
|
||||||
|
Some(adt.struct_variant())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
|
||||||
|
// Reject tuple structs for now, braced and unit structs are allowed.
|
||||||
|
span_err!(self.tcx.sess, span, E0071,
|
||||||
|
"`{}` does not name a struct or a struct variant",
|
||||||
|
pprust::path_to_string(path));
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
variant
|
||||||
|
}
|
||||||
|
|
||||||
fn check_expr_struct(&self,
|
fn check_expr_struct(&self,
|
||||||
expr: &hir::Expr,
|
expr: &hir::Expr,
|
||||||
path: &hir::Path,
|
path: &hir::Path,
|
||||||
fields: &'gcx [hir::Field],
|
fields: &'gcx [hir::Field],
|
||||||
base_expr: &'gcx Option<P<hir::Expr>>)
|
base_expr: &'gcx Option<P<hir::Expr>>)
|
||||||
{
|
{
|
||||||
let tcx = self.tcx;
|
|
||||||
|
|
||||||
// Find the relevant variant
|
// Find the relevant variant
|
||||||
let def = tcx.expect_def(expr.id);
|
let def = self.finish_resolving_struct_path(path, expr.id, expr.span);
|
||||||
if def == Def::Err {
|
let variant = if let Some(variant) = self.check_struct_path(def, path, expr.span) {
|
||||||
self.set_tainted_by_errors();
|
variant
|
||||||
|
} else {
|
||||||
self.check_struct_fields_on_error(expr.id, fields, base_expr);
|
self.check_struct_fields_on_error(expr.id, fields, base_expr);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
let variant = match self.def_struct_variant(def, path.span) {
|
|
||||||
Some((_, variant)) => variant,
|
|
||||||
None => {
|
|
||||||
span_err!(self.tcx.sess, path.span, E0071,
|
|
||||||
"`{}` does not name a structure",
|
|
||||||
pprust::path_to_string(path));
|
|
||||||
self.check_struct_fields_on_error(expr.id, fields, base_expr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let expr_ty = self.instantiate_type(def.def_id(), path);
|
let expr_ty = self.instantiate_type_path(def.def_id(), path, expr.id);
|
||||||
self.write_ty(expr.id, expr_ty);
|
|
||||||
|
|
||||||
self.check_expr_struct_fields(expr_ty, path.span, variant, fields,
|
self.check_expr_struct_fields(expr_ty, path.span, variant, fields,
|
||||||
base_expr.is_none());
|
base_expr.is_none());
|
||||||
|
@ -3190,13 +3180,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
expr.id,
|
expr.id,
|
||||||
adt.struct_variant().fields.iter().map(|f| {
|
adt.struct_variant().fields.iter().map(|f| {
|
||||||
self.normalize_associated_types_in(
|
self.normalize_associated_types_in(
|
||||||
expr.span, &f.ty(tcx, substs)
|
expr.span, &f.ty(self.tcx, substs)
|
||||||
)
|
)
|
||||||
}).collect()
|
}).collect()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
span_err!(tcx.sess, base_expr.span, E0436,
|
span_err!(self.tcx.sess, base_expr.span, E0436,
|
||||||
"functional record update syntax requires a struct");
|
"functional record update syntax requires a struct");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3349,12 +3339,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
hir::ExprPath(ref opt_qself, ref path) => {
|
hir::ExprPath(ref opt_qself, ref path) => {
|
||||||
let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
|
let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
|
||||||
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(id),
|
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
|
||||||
opt_self_ty, path, expr.span, expr.id);
|
expr.id, expr.span);
|
||||||
if def != Def::Err {
|
if def != Def::Err {
|
||||||
let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
|
let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
|
||||||
def);
|
def);
|
||||||
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, expr.span, id);
|
self.instantiate_value_path(segments, scheme, &predicates,
|
||||||
|
opt_ty, def, expr.span, id);
|
||||||
} else {
|
} else {
|
||||||
self.set_tainted_by_errors();
|
self.set_tainted_by_errors();
|
||||||
self.write_error(id);
|
self.write_error(id);
|
||||||
|
@ -3695,18 +3686,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
expected);
|
expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
|
||||||
|
// The newly resolved definition is written into `def_map`.
|
||||||
|
pub fn finish_resolving_struct_path(&self,
|
||||||
|
path: &hir::Path,
|
||||||
|
node_id: ast::NodeId,
|
||||||
|
span: Span)
|
||||||
|
-> Def
|
||||||
|
{
|
||||||
|
let path_res = self.tcx().expect_resolution(node_id);
|
||||||
|
if path_res.depth == 0 {
|
||||||
|
// If fully resolved already, we don't have to do anything.
|
||||||
|
path_res.base_def
|
||||||
|
} else {
|
||||||
|
let base_ty_end = path.segments.len() - path_res.depth;
|
||||||
|
let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span,
|
||||||
|
PathParamMode::Optional,
|
||||||
|
path_res.base_def,
|
||||||
|
None,
|
||||||
|
node_id,
|
||||||
|
&path.segments[..base_ty_end],
|
||||||
|
&path.segments[base_ty_end..]);
|
||||||
|
// Write back the new resolution.
|
||||||
|
self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
|
||||||
|
def
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve associated value path into a base type and associated constant or method definition.
|
// Resolve associated value path into a base type and associated constant or method definition.
|
||||||
// The newly resolved definition is written into `def_map`.
|
// The newly resolved definition is written into `def_map`.
|
||||||
pub fn resolve_ty_and_def_ufcs<'b>(&self,
|
pub fn resolve_ty_and_def_ufcs<'b>(&self,
|
||||||
path_res: PathResolution,
|
|
||||||
opt_self_ty: Option<Ty<'tcx>>,
|
opt_self_ty: Option<Ty<'tcx>>,
|
||||||
path: &'b hir::Path,
|
path: &'b hir::Path,
|
||||||
span: Span,
|
node_id: ast::NodeId,
|
||||||
node_id: ast::NodeId)
|
span: Span)
|
||||||
-> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
|
-> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
|
||||||
{
|
{
|
||||||
// If fully resolved already, we don't have to do anything.
|
let path_res = self.tcx().expect_resolution(node_id);
|
||||||
if path_res.depth == 0 {
|
if path_res.depth == 0 {
|
||||||
|
// If fully resolved already, we don't have to do anything.
|
||||||
(path_res.base_def, opt_self_ty, &path.segments)
|
(path_res.base_def, opt_self_ty, &path.segments)
|
||||||
} else {
|
} else {
|
||||||
// Try to resolve everything except for the last segment as a type.
|
// Try to resolve everything except for the last segment as a type.
|
||||||
|
@ -3975,15 +3993,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// 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_path(&self,
|
pub fn instantiate_value_path(&self,
|
||||||
segments: &[hir::PathSegment],
|
segments: &[hir::PathSegment],
|
||||||
type_scheme: TypeScheme<'tcx>,
|
type_scheme: TypeScheme<'tcx>,
|
||||||
type_predicates: &ty::GenericPredicates<'tcx>,
|
type_predicates: &ty::GenericPredicates<'tcx>,
|
||||||
opt_self_ty: Option<Ty<'tcx>>,
|
opt_self_ty: Option<Ty<'tcx>>,
|
||||||
def: Def,
|
def: Def,
|
||||||
span: Span,
|
span: Span,
|
||||||
node_id: ast::NodeId) {
|
node_id: ast::NodeId)
|
||||||
debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
|
-> Ty<'tcx> {
|
||||||
|
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
|
||||||
segments,
|
segments,
|
||||||
def,
|
def,
|
||||||
node_id,
|
node_id,
|
||||||
|
@ -4012,7 +4031,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// actually pass through this function, but rather the
|
// actually pass through this function, but rather the
|
||||||
// `ast_ty_to_ty` function in `astconv`. However, in the case
|
// `ast_ty_to_ty` function in `astconv`. However, in the case
|
||||||
// of struct patterns (and maybe literals) we do invoke
|
// of struct patterns (and maybe literals) we do invoke
|
||||||
// `instantiate_path` to get the general type of an instance of
|
// `instantiate_value_path` to get the general type of an instance of
|
||||||
// a struct. (In these cases, there are actually no type
|
// a struct. (In these cases, there are actually no type
|
||||||
// parameters permitted at present, but perhaps we will allow
|
// parameters permitted at present, but perhaps we will allow
|
||||||
// them in the future.)
|
// them in the future.)
|
||||||
|
@ -4235,20 +4254,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
span_bug!(span,
|
span_bug!(span,
|
||||||
"instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
|
"instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
|
||||||
self_ty,
|
self_ty,
|
||||||
impl_ty);
|
impl_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("instantiate_path: type of {:?} is {:?}",
|
debug!("instantiate_value_path: type of {:?} is {:?}",
|
||||||
node_id,
|
node_id,
|
||||||
ty_substituted);
|
ty_substituted);
|
||||||
self.write_ty(node_id, ty_substituted);
|
self.write_ty(node_id, ty_substituted);
|
||||||
self.write_substs(node_id, ty::ItemSubsts {
|
self.write_substs(node_id, ty::ItemSubsts {
|
||||||
substs: substs
|
substs: substs
|
||||||
});
|
});
|
||||||
|
ty_substituted
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the parameters that the user provided and adds them to `substs`. If too many
|
/// Finds the parameters that the user provided and adds them to `substs`. If too many
|
||||||
|
|
|
@ -1895,33 +1895,6 @@ fn my_start(argc: isize, argv: *const *const u8) -> isize {
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
E0163: r##"
|
|
||||||
This error means that an attempt was made to match an enum variant as a
|
|
||||||
struct type when the variant isn't a struct type:
|
|
||||||
|
|
||||||
```compile_fail
|
|
||||||
enum Foo { B(u32) }
|
|
||||||
|
|
||||||
fn bar(foo: Foo) -> u32 {
|
|
||||||
match foo {
|
|
||||||
B{i} => i, // error E0163
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Try using `()` instead:
|
|
||||||
|
|
||||||
```
|
|
||||||
enum Foo { B(u32) }
|
|
||||||
|
|
||||||
fn bar(foo: Foo) -> u32 {
|
|
||||||
match foo {
|
|
||||||
Foo::B(i) => i,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
"##,
|
|
||||||
|
|
||||||
E0164: r##"
|
E0164: r##"
|
||||||
This error means that an attempt was made to match a struct type enum
|
This error means that an attempt was made to match a struct type enum
|
||||||
variant as a non-struct type:
|
variant as a non-struct type:
|
||||||
|
@ -4070,6 +4043,7 @@ register_diagnostics! {
|
||||||
// E0129,
|
// E0129,
|
||||||
// E0141,
|
// E0141,
|
||||||
// E0159, // use of trait `{}` as struct constructor
|
// E0159, // use of trait `{}` as struct constructor
|
||||||
|
// E0163, // merged into E0071
|
||||||
E0167,
|
E0167,
|
||||||
// E0168,
|
// E0168,
|
||||||
// E0173, // manual implementations of unboxed closure traits are experimental
|
// E0173, // manual implementations of unboxed closure traits are experimental
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
enum Foo { B(u32) }
|
|
||||||
|
|
||||||
fn bar(foo: Foo) -> u32 {
|
|
||||||
match foo {
|
|
||||||
Foo::B { i } => i, //~ ERROR E0163
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ pub struct GslResult {
|
||||||
|
|
||||||
impl GslResult {
|
impl GslResult {
|
||||||
pub fn new() -> GslResult {
|
pub fn new() -> GslResult {
|
||||||
Result { //~ ERROR: `Result` does not name a structure
|
Result { //~ ERROR: `Result` does not name a struct or a struct variant
|
||||||
val: 0f64,
|
val: 0f64,
|
||||||
err: 0f64
|
err: 0f64
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
mod foo {}
|
mod foo {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let p = foo { x: () }; //~ ERROR `foo` does not name a structure
|
let p = foo { x: () }; //~ ERROR `foo` does not name a struct or a struct variant
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,5 @@ enum Foo {
|
||||||
fn main() {
|
fn main() {
|
||||||
match Foo::Bar(1) {
|
match Foo::Bar(1) {
|
||||||
Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
|
Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
|
||||||
//~^ ERROR `Foo` does not name a struct or a struct variant
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
mod MyMod {}
|
mod MyMod {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a structure
|
let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a struct or a struct variant
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,5 @@ fn main() {
|
||||||
match 'a' {
|
match 'a' {
|
||||||
char{ch} => true
|
char{ch} => true
|
||||||
//~^ ERROR expected variant, struct or type alias, found builtin type `char`
|
//~^ ERROR expected variant, struct or type alias, found builtin type `char`
|
||||||
//~| ERROR `char` does not name a struct or a struct variant
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,10 @@
|
||||||
mod A {}
|
mod A {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let u = A { x: 1 }; //~ ERROR `A` does not name a structure
|
let u = A { x: 1 }; //~ ERROR `A` does not name a struct or a struct variant
|
||||||
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
|
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a struct or a struct variant
|
||||||
match () {
|
match () {
|
||||||
A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
|
A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
|
||||||
//~^ ERROR `A` does not name a struct or a struct variant
|
|
||||||
u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
|
u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
|
||||||
//~^ ERROR `u32` does not name a struct or a struct variant
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ enum Enum {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Foo(1);
|
let x = Foo(1);
|
||||||
Foo { ..x }; //~ ERROR `Foo` does not name a structure
|
Foo { ..x }; //~ ERROR `Foo` does not name a struct or a struct variant
|
||||||
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
|
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
|
||||||
|
|
||||||
let x = Bar;
|
let x = Bar;
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
struct NonCopyable(());
|
struct NonCopyable(());
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a structure
|
let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a struct or a struct variant
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
struct T { i: i32 }
|
struct T { i: i32 }
|
||||||
fn f<T>() {
|
fn f<T>() {
|
||||||
let t = T { i: 0 }; //~ ERROR `T` does not name a structure
|
let t = T { i: 0 }; //~ ERROR `T` does not name a struct or a struct variant
|
||||||
}
|
}
|
||||||
|
|
||||||
mod Foo {
|
mod Foo {
|
||||||
|
|
|
@ -12,5 +12,5 @@ trait TraitNotAStruct {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
TraitNotAStruct{ value: 0 };
|
TraitNotAStruct{ value: 0 };
|
||||||
//~^ ERROR: `TraitNotAStruct` does not name a structure [E0071]
|
//~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue