From ce32daa6b7f14084cb29466b985128c8938f942a Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 16 Mar 2017 20:39:41 +0000 Subject: [PATCH 1/6] Fix regression when `include!()`ing a `macro_rules!` containing a `$crate::` path. --- src/librustc_resolve/build_reduced_graph.rs | 5 ++++- src/test/run-pass/auxiliary/issue_40469.rs | 11 +++++++++++ src/test/run-pass/issue-40469.rs | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/auxiliary/issue_40469.rs create mode 100644 src/test/run-pass/issue-40469.rs diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 03c61067d64c2..be905a9d0f94a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -23,7 +23,7 @@ use {resolve_error, resolve_struct_error, ResolutionError}; use rustc::middle::cstore::LoadedMacro; use rustc::hir::def::*; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CrateNum, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefId}; use rustc::ty; use std::cell::Cell; @@ -496,6 +496,9 @@ impl<'a> Resolver<'a> { let def_id = self.macro_defs[&expansion]; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] + } else if def_id.krate == BUILTIN_MACROS_CRATE { + // FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469. + self.graph_root } else { let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); self.get_extern_crate_root(module_def_id.krate) diff --git a/src/test/run-pass/auxiliary/issue_40469.rs b/src/test/run-pass/auxiliary/issue_40469.rs new file mode 100644 index 0000000000000..4970bba431a84 --- /dev/null +++ b/src/test/run-pass/auxiliary/issue_40469.rs @@ -0,0 +1,11 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! m { () => { $crate::main(); } } diff --git a/src/test/run-pass/issue-40469.rs b/src/test/run-pass/issue-40469.rs new file mode 100644 index 0000000000000..30055e532cd45 --- /dev/null +++ b/src/test/run-pass/issue-40469.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty issue #37195 + +#![allow(dead_code)] + +include!("auxiliary/issue_40469.rs"); +fn f() { m!(); } + +fn main() {} From 41f6bad85562abe2200c9918ff807b6bbdacc78d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 9 Mar 2017 21:05:56 +0200 Subject: [PATCH 2/6] Rename expected_types_for_fn_args to expected_inputs_for_expected_output. --- src/librustc_typeck/check/callee.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 4b88f5acf42da..529ee107c46ce 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -254,7 +254,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Call the generic checker. let expected_arg_tys = - self.expected_types_for_fn_args(call_expr.span, + self.expected_inputs_for_expected_output(call_expr.span, expected, fn_sig.output(), fn_sig.inputs()); @@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // do know the types expected for each argument and the return // type. - let expected_arg_tys = self.expected_types_for_fn_args(call_expr.span, + let expected_arg_tys = self.expected_inputs_for_expected_output(call_expr.span, expected, fn_sig.output().clone(), fn_sig.inputs()); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5a582a523ea1c..95d0ee51d3443 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2292,7 +2292,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match method_fn_ty.sty { ty::TyFnDef(def_id, .., ref fty) => { // HACK(eddyb) ignore self in the definition (see above). - let expected_arg_tys = self.expected_types_for_fn_args( + let expected_arg_tys = self.expected_inputs_for_expected_output( sp, expected, fty.0.output(), @@ -2645,14 +2645,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { TypeAndSubsts { substs: substs, ty: substd_ty } } - /// Unifies the return type with the expected type early, for more coercions - /// and forward type information on the argument expressions. - fn expected_types_for_fn_args(&self, - call_span: Span, - expected_ret: Expectation<'tcx>, - formal_ret: Ty<'tcx>, - formal_args: &[Ty<'tcx>]) - -> Vec> { + /// Unifies the output type with the expected type early, for more coercions + /// and forward type information on the input expressions. + fn expected_inputs_for_expected_output(&self, + call_span: Span, + expected_ret: Expectation<'tcx>, + formal_ret: Ty<'tcx>, + formal_args: &[Ty<'tcx>]) + -> Vec> { let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| { self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || { // Attempt to apply a subtyping relationship between the formal @@ -2675,7 +2675,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }).collect()) }).ok() }).unwrap_or(vec![]); - debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})", + debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})", formal_args, formal_ret, expected_args, expected_ret); expected_args From 52e7c9c29e029cf53ea92234121101cb3baabdb7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 9 Mar 2017 21:06:18 +0200 Subject: [PATCH 3/6] Propagate expected type hints through struct literals. --- src/librustc_typeck/check/mod.rs | 29 +++++++++++++++++++++-------- src/test/run-pass/issue-31260.rs | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 src/test/run-pass/issue-31260.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 95d0ee51d3443..f36254a8a10ea 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3032,14 +3032,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_struct_fields(&self, adt_ty: Ty<'tcx>, + expected: Expectation<'tcx>, expr_id: ast::NodeId, span: Span, variant: &'tcx ty::VariantDef, ast_fields: &'gcx [hir::Field], check_completeness: bool) { let tcx = self.tcx; - let (substs, adt_kind, kind_name) = match adt_ty.sty { - ty::TyAdt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()), + + let adt_ty_hint = + self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]) + .get(0).cloned().unwrap_or(adt_ty); + + let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) { + (&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => { + (substs, hint_substs, adt.adt_kind(), adt.variant_descr()) + } _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields") }; @@ -3054,10 +3062,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Typecheck each field. for field in ast_fields { - let expected_field_type; + let final_field_type; + let field_type_hint; if let Some(v_field) = remaining_fields.remove(&field.name.node) { - expected_field_type = self.field_ty(field.span, v_field, substs); + final_field_type = self.field_ty(field.span, v_field, substs); + field_type_hint = self.field_ty(field.span, v_field, hint_substs); seen_fields.insert(field.name.node, field.span); @@ -3069,7 +3079,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } else { error_happened = true; - expected_field_type = tcx.types.err; + final_field_type = tcx.types.err; + field_type_hint = tcx.types.err; if let Some(_) = variant.find_field_named(field.name.node) { let mut err = struct_span_err!(self.tcx.sess, field.name.span, @@ -3091,7 +3102,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Make sure to give a type to the field even if there's // an error, so we can continue typechecking - self.check_expr_coercable_to_type(&field.expr, expected_field_type); + let ty = self.check_expr_with_hint(&field.expr, field_type_hint); + self.demand_coerce(&field.expr, ty, final_field_type); } // Make sure the programmer specified correct number of fields. @@ -3201,6 +3213,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_struct(&self, expr: &hir::Expr, + expected: Expectation<'tcx>, qpath: &hir::QPath, fields: &'gcx [hir::Field], base_expr: &'gcx Option>) -> Ty<'tcx> @@ -3219,7 +3232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::QPath::TypeRelative(ref qself, _) => qself.span }; - self.check_expr_struct_fields(struct_ty, expr.id, path_span, variant, fields, + self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { self.check_expr_has_type(base_expr, struct_ty); @@ -3764,7 +3777,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } hir::ExprStruct(ref qpath, ref fields, ref base_expr) => { - self.check_expr_struct(expr, qpath, fields, base_expr) + self.check_expr_struct(expr, expected, qpath, fields, base_expr) } hir::ExprField(ref base, ref field) => { self.check_field(expr, lvalue_pref, &base, field) diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs new file mode 100644 index 0000000000000..e771fc7464d00 --- /dev/null +++ b/src/test/run-pass/issue-31260.rs @@ -0,0 +1,20 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct Struct { + pub field: K, +} + +// Partial fix for #31260, doesn't work without {...}. +static STRUCT: Struct<&'static [u8]> = Struct { + field: {&[1]} +}; + +fn main() {} From 4d605c0c013b443e8d6254bee8abc5659e63cc1f Mon Sep 17 00:00:00 2001 From: Austin Bonander Date: Wed, 15 Mar 2017 01:27:43 -0700 Subject: [PATCH 4/6] Correctly get source for metadata crate type; replace `unwrap()` with `expect()` --- src/librustc_metadata/creader.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 49dcffb4830a1..e9b97e63399ed 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -236,7 +236,8 @@ impl<'a> CrateLoader<'a> { // path (this is a top-level dependency) as we don't want to // implicitly load anything inside the dependency lookup path. let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref()) - .unwrap().1; + .or(source.rmeta.as_ref()) + .expect("No sources for crate").1; if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) { ret = Some(cnum); } From 1dc25bdb8bb925e8f18ec865b9aafce82993227c Mon Sep 17 00:00:00 2001 From: Austin Bonander Date: Thu, 16 Mar 2017 14:41:08 -0700 Subject: [PATCH 5/6] Regression test for rust-lang/rust#40535 --- src/test/run-make/issue-40535/Makefile | 11 +++++++++++ src/test/run-make/issue-40535/bar.rs | 13 +++++++++++++ src/test/run-make/issue-40535/baz.rs | 11 +++++++++++ src/test/run-make/issue-40535/foo.rs | 14 ++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 src/test/run-make/issue-40535/Makefile create mode 100644 src/test/run-make/issue-40535/bar.rs create mode 100644 src/test/run-make/issue-40535/baz.rs create mode 100644 src/test/run-make/issue-40535/foo.rs diff --git a/src/test/run-make/issue-40535/Makefile b/src/test/run-make/issue-40535/Makefile new file mode 100644 index 0000000000000..7d513a86a7fa5 --- /dev/null +++ b/src/test/run-make/issue-40535/Makefile @@ -0,0 +1,11 @@ +# The ICE occurred in the following situation: +# * `foo` declares `extern crate bar, baz`, depends only on `bar` (forgetting `baz` in `Cargo.toml`) +# * `bar` declares and depends on `extern crate baz` +# * All crates built in metadata-only mode (`cargo check`) +all: + # cc https://github.com/rust-lang/rust/issues/40623 + $(RUSTC) baz.rs --emit=metadata --out-dir=$(TMPDIR) + $(RUSTC) bar.rs --emit=metadata --extern baz=$(TMPDIR)/libbaz.rmeta --out-dir=$(TMPDIR) + $(RUSTC) foo.rs --emit=metadata --extern bar=$(TMPDIR)/libbar.rmeta --out-dir=$(TMPDIR) 2>&1 | \ + grep -vq "unexpectedly panicked" + # ^ Succeeds if it doesn't find the ICE message diff --git a/src/test/run-make/issue-40535/bar.rs b/src/test/run-make/issue-40535/bar.rs new file mode 100644 index 0000000000000..4c22f181975b8 --- /dev/null +++ b/src/test/run-make/issue-40535/bar.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] + +extern crate baz; diff --git a/src/test/run-make/issue-40535/baz.rs b/src/test/run-make/issue-40535/baz.rs new file mode 100644 index 0000000000000..737a918a0398d --- /dev/null +++ b/src/test/run-make/issue-40535/baz.rs @@ -0,0 +1,11 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] diff --git a/src/test/run-make/issue-40535/foo.rs b/src/test/run-make/issue-40535/foo.rs new file mode 100644 index 0000000000000..53a8c8636b148 --- /dev/null +++ b/src/test/run-make/issue-40535/foo.rs @@ -0,0 +1,14 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] + +extern crate bar; +extern crate baz; From 3808ae855b9a55d88e3f23f5a63e807c4df3a373 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 Mar 2017 07:53:15 -0700 Subject: [PATCH 6/6] Bump beta to .2 --- src/bootstrap/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 2607ce412f108..cb6e1c2b57e7e 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -28,7 +28,7 @@ pub const CFG_RELEASE_NUM: &'static str = "1.17.0"; // An optional number to put after the label, e.g. '.2' -> '-beta.2' // Be sure to make this starts with a dot to conform to semver pre-release // versions (section 9) -pub const CFG_PRERELEASE_VERSION: &'static str = ".1"; +pub const CFG_PRERELEASE_VERSION: &'static str = ".2"; pub struct GitInfo { inner: Option,