Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Self in struct expressions and patterns #37035

Merged
merged 3 commits into from
Oct 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
delegate.matched_pat(pat, downcast_cmt, match_mode);
}
Some(Def::Struct(..)) | Some(Def::StructCtor(..)) | Some(Def::Union(..)) |
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => {
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) | Some(Def::SelfTy(..)) => {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, cmt_pat, match_mode);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1698,7 +1698,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
match def {
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(),
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.struct_variant(),
_ => bug!("unexpected def {:?} in variant_of_def", def)
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use ty::{TyBool, TyChar, TyAdt};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::TyClosure;
use ty::{TyClosure, TyProjection, TyAnon};
use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::fold::{TypeFolder, TypeVisitor};
Expand Down Expand Up @@ -879,8 +879,8 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
})
}
TyTrait(ref data) => write!(f, "{}", data),
ty::TyProjection(ref data) => write!(f, "{}", data),
ty::TyAnon(def_id, substs) => {
TyProjection(ref data) => write!(f, "{}", data),
TyAnon(def_id, substs) => {
ty::tls::with(|tcx| {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_const_eval/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
}

Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => {
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
PatternKind::Leaf { subpatterns: subpatterns }
}

Expand Down
8 changes: 5 additions & 3 deletions src/librustc_passes/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
}
hir::ExprStruct(..) => {
// unsafe_cell_type doesn't necessarily exist with no_core
if Some(v.tcx.expect_def(e.id).def_id()) == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM);
if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty {
// unsafe_cell_type doesn't necessarily exist with no_core
if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM);
}
}
}

Expand Down
26 changes: 1 addition & 25 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -860,31 +860,6 @@ match (A, B, C) {
```
"##,

E0422: r##"
You are trying to use an identifier that is either undefined or not a struct.

Erroneous code example:

``` compile_fail,E0422
fn main () {
let x = Foo { x: 1, y: 2 };
}
```

In this case, `Foo` is undefined, so it inherently isn't anything, and
definitely not a struct.

```compile_fail,E0422
fn main () {
let foo = 1;
let x = foo { x: 1, y: 2 };
}
```

In this case, `foo` is defined, but is not a struct, so Rust can't use it as
one.
"##,

E0423: r##"
A `struct` variant name was used like a function name.

Expand Down Expand Up @@ -1503,6 +1478,7 @@ register_diagnostics! {
// E0419, merged into 531
// E0420, merged into 532
// E0421, merged into 531
// E0422, merged into 531/532
E0531, // unresolved pattern path kind `name`
E0532, // expected pattern path kind, found another pattern path kind
// E0427, merged into 530
Expand Down
49 changes: 14 additions & 35 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ enum ResolutionError<'a> {
IdentifierBoundMoreThanOnceInParameterList(&'a str),
/// error E0416: identifier is bound more than once in the same pattern
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
/// error E0422: does not name a struct
DoesNotNameAStruct(&'a str),
/// error E0423: is a struct variant name, but this expression uses it like a function name
StructVariantUsedAsFunction(&'a str),
/// error E0424: `self` is not available in a static method
Expand Down Expand Up @@ -336,15 +334,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
err.span_label(span, &format!("used in a pattern more than once"));
err
}
ResolutionError::DoesNotNameAStruct(name) => {
let mut err = struct_span_err!(resolver.session,
span,
E0422,
"`{}` does not name a structure",
name);
err.span_label(span, &format!("not a structure"));
err
}
ResolutionError::StructVariantUsedAsFunction(path_name) => {
let mut err = struct_span_err!(resolver.session,
span,
Expand Down Expand Up @@ -2383,6 +2372,18 @@ impl<'a> Resolver<'a> {
self.record_def(pat_id, resolution);
}

fn resolve_struct_path(&mut self, node_id: NodeId, path: &Path) {
// Resolution logic is equivalent for expressions and patterns,
// reuse `resolve_pattern_path` for both.
self.resolve_pattern_path(node_id, None, path, TypeNS, |def| {
match def {
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
_ => false,
}
}, "struct, variant or union type");
}

fn resolve_pattern(&mut self,
pat: &Pat,
pat_src: PatternSource,
Expand Down Expand Up @@ -2460,13 +2461,7 @@ impl<'a> Resolver<'a> {
}

PatKind::Struct(ref path, ..) => {
self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| {
match def {
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => true,
_ => false,
}
}, "variant, struct or type alias");
self.resolve_struct_path(pat.id, path);
}

_ => {}
Expand Down Expand Up @@ -3024,23 +3019,7 @@ impl<'a> Resolver<'a> {
}

ExprKind::Struct(ref path, ..) => {
// Resolve the path to the structure it goes to. We don't
// check to ensure that the path is actually a structure; that
// is checked later during typeck.
match self.resolve_path(expr.id, path, 0, TypeNS) {
Ok(definition) => self.record_def(expr.id, definition),
Err(true) => self.record_def(expr.id, err_path_resolution()),
Err(false) => {
debug!("(resolving expression) didn't find struct def",);

resolve_error(self,
path.span,
ResolutionError::DoesNotNameAStruct(
&path_names_to_string(path, 0))
);
self.record_def(expr.id, err_path_resolution());
}
}
self.resolve_struct_path(expr.id, path);

visit::walk_expr(self, expr);
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1493,7 +1493,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
Def::StructCtor(..) | Def::VariantCtor(..) |
Def::Const(..) | Def::AssociatedConst(..) |
Def::Struct(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) => {
Def::TyAlias(..) | Def::AssociatedTy(..) |
Def::SelfTy(..) => {
paths_to_process.push((id, p.clone(), Some(ref_kind)))
}
def => error!("unexpected definition kind when processing collected paths: {:?}",
Expand Down
22 changes: 18 additions & 4 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
def: Def,
opt_self_ty: Option<Ty<'tcx>>,
base_path_ref_id: ast::NodeId,
base_segments: &[hir::PathSegment])
base_segments: &[hir::PathSegment],
permit_variants: bool)
-> Ty<'tcx> {
let tcx = self.tcx();

Expand Down Expand Up @@ -1515,6 +1516,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
did,
base_segments.last().unwrap())
}
Def::Variant(did) if permit_variants => {
// Convert "variant type" as if it were a real type.
// The resulting `Ty` is type of the variant's enum for now.
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
self.ast_path_to_ty(rscope,
span,
param_mode,
tcx.parent_def_id(did).unwrap(),
base_segments.last().unwrap())
}
Def::TyParam(did) => {
tcx.prohibit_type_params(base_segments);

Expand Down Expand Up @@ -1604,7 +1615,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
opt_self_ty: Option<Ty<'tcx>>,
base_path_ref_id: ast::NodeId,
base_segments: &[hir::PathSegment],
assoc_segments: &[hir::PathSegment])
assoc_segments: &[hir::PathSegment],
permit_variants: bool)
-> (Ty<'tcx>, Def) {
// Convert the base type.
debug!("finish_resolving_def_to_ty(base_def={:?}, \
Expand All @@ -1619,7 +1631,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
base_def,
opt_self_ty,
base_path_ref_id,
base_segments);
base_segments,
permit_variants);
debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);

// If any associated type segments remain, attempt to resolve them.
Expand Down Expand Up @@ -1775,7 +1788,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
opt_self_ty,
ast_ty.id,
&path.segments[..base_ty_end],
&path.segments[base_ty_end..]);
&path.segments[base_ty_end..],
false);

// Write back the new resolution.
if path_res.depth != 0 {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected: Ty<'tcx>) -> Ty<'tcx>
{
// Resolve the path and check the definition for errors.
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id,
pat.span) {
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id) {
variant_ty
} else {
for field in fields {
Expand Down
Loading