Skip to content
Merged
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
27 changes: 27 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
Version 1.12.1 (2016-10-20)
===========================

Regression Fixes
----------------

* [ICE: 'rustc' panicked at 'assertion failed: concrete_substs.is_normalized_for_trans()' #36381][36381]
* [Confusion with double negation and booleans][36856]
* [rustc 1.12.0 fails with SIGSEGV in release mode (syn crate 0.8.0)][36875]
* [Rustc 1.12.0 Windows build of `ethcore` crate fails with LLVM error][36924]
* [1.12.0: High memory usage when linking in release mode with debug info][36926]
* [Corrupted memory after updated to 1.12][36936]
* ["Let NullaryConstructor = something;" causes internal compiler error: "tried to overwrite interned AdtDef"][37026]
* [Fix ICE: inject bitcast if types mismatch for invokes/calls/stores][37112]
* [debuginfo: Handle spread_arg case in MIR-trans in a more stable way.][37153]

[36381]: https://github.com/rust-lang/rust/issues/36381
[36856]: https://github.com/rust-lang/rust/issues/36856
[36875]: https://github.com/rust-lang/rust/issues/36875
[36924]: https://github.com/rust-lang/rust/issues/36924
[36926]: https://github.com/rust-lang/rust/issues/36926
[36936]: https://github.com/rust-lang/rust/issues/36936
[37026]: https://github.com/rust-lang/rust/issues/37026
[37112]: https://github.com/rust-lang/rust/issues/37112
[37153]: https://github.com/rust-lang/rust/issues/37153


Version 1.12.0 (2016-09-29)
===========================

28 changes: 6 additions & 22 deletions mk/main.mk
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.13.0
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release
# versions (section 9)
CFG_PRERELEASE_VERSION=.2
CFG_PRERELEASE_VERSION=.3

ifeq ($(CFG_RELEASE_CHANNEL),stable)
# This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly"
@@ -53,17 +53,6 @@ endif
# versions in the same place
CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(CFG_HASH_COMMAND))

# A magic value that allows the compiler to use unstable features during the
# bootstrap even when doing so would normally be an error because of feature
# staging or because the build turns on warnings-as-errors and unstable features
# default to warnings. The build has to match this key in an env var.
#
# This value is keyed off the release to ensure that all compilers for one
# particular release have the same bootstrap key. Note that this is
# intentionally not "secure" by any definition, this is largely just a deterrent
# from users enabling unstable features on the stable compiler.
CFG_BOOTSTRAP_KEY=$(CFG_FILENAME_EXTRA)

# If local-rust is the same as the current version, then force a local-rebuild
ifdef CFG_ENABLE_LOCAL_RUST
ifeq ($(CFG_RELEASE),\
@@ -73,14 +62,6 @@ ifeq ($(CFG_RELEASE),\
endif
endif

# The stage0 compiler needs to use the previous key recorded in src/stage0.txt,
# except for local-rebuild when it just uses the same current key.
ifdef CFG_ENABLE_LOCAL_REBUILD
CFG_BOOTSTRAP_KEY_STAGE0=$(CFG_BOOTSTRAP_KEY)
else
CFG_BOOTSTRAP_KEY_STAGE0=$(shell sed -ne 's/^rustc_key: //p' $(S)src/stage0.txt)
endif

# The name of the package to use for creating tarballs, installers etc.
CFG_PACKAGE_NAME=rustc-$(CFG_PACKAGE_VERS)

@@ -387,13 +368,16 @@ CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATUR
# Turn on feature-staging
export CFG_DISABLE_UNSTABLE_FEATURES
# Subvert unstable feature lints to do the self-build
export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY)
export RUSTC_BOOTSTRAP
endif
export CFG_BOOTSTRAP_KEY
ifdef CFG_MUSL_ROOT
export CFG_MUSL_ROOT
endif

# FIXME: Transitionary measure to bootstrap using the old bootstrap logic.
# Remove this once the bootstrap compiler uses the new login in Issue #36548.
export RUSTC_BOOTSTRAP_KEY=5c6cf767

######################################################################
# Per-stage targets and runner
######################################################################
21 changes: 0 additions & 21 deletions mk/target.mk
Original file line number Diff line number Diff line change
@@ -42,23 +42,6 @@ $(foreach host,$(CFG_HOST), \
$(foreach crate,$(CRATES), \
$(eval $(call RUST_CRATE_FULLDEPS,$(stage),$(target),$(host),$(crate)))))))

# $(1) stage
# $(2) target
# $(3) host
define DEFINE_BOOTSTRAP_KEY
BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3) := $$(CFG_BOOTSTRAP_KEY)
ifeq ($(1),0)
ifeq ($(3),$$(CFG_BUILD))
BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3) := $$(CFG_BOOTSTRAP_KEY_STAGE0)
endif
endif
endef

$(foreach host,$(CFG_TARGET), \
$(foreach target,$(CFG_TARGET), \
$(foreach stage,$(STAGES), \
$(eval $(call DEFINE_BOOTSTRAP_KEY,$(stage),$(target),$(host))))))

# RUST_TARGET_STAGE_N template: This defines how target artifacts are built
# for all stage/target architecture combinations. This is one giant rule which
# works as follows:
@@ -83,8 +66,6 @@ $(foreach host,$(CFG_TARGET), \
define RUST_TARGET_STAGE_N

$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER_HOST_TRIPLE = $(2)
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
export RUSTC_BOOTSTRAP_KEY := $$(BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3))
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
$$(CRATEFILE_$(4)) \
$$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \
@@ -132,8 +113,6 @@ endef
# $(4) - name of the tool being built
define TARGET_TOOL

$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
export RUSTC_BOOTSTRAP_KEY := $$(BOOTSTRAP_KEY$(1)_T_$(2)_H_$(3))
$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
$$(TOOL_SOURCE_$(4)) \
$$(TOOL_INPUTS_$(4)) \
2 changes: 1 addition & 1 deletion src/bootstrap/check.rs
Original file line number Diff line number Diff line change
@@ -185,7 +185,7 @@ pub fn compiletest(build: &Build,
}
}
}
build.add_bootstrap_key(compiler, &mut cmd);
build.add_bootstrap_key(&mut cmd);

cmd.arg("--adb-path").arg("adb");
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
3 changes: 1 addition & 2 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
@@ -133,7 +133,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
let file = t!(file);
let mut cmd = Command::new(&compiler_path);
build.add_bootstrap_key(&compiler, &mut cmd);
build.add_bootstrap_key(&mut cmd);
build.run(cmd.arg("--target").arg(target)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
@@ -199,7 +199,6 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("CFG_RELEASE", &build.release)
.env("CFG_RELEASE_CHANNEL", &build.config.channel)
.env("CFG_VERSION", &build.version)
.env("CFG_BOOTSTRAP_KEY", &build.bootstrap_key)
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(String::new()))
.env("CFG_LIBDIR_RELATIVE", "lib");

17 changes: 6 additions & 11 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
@@ -647,7 +647,7 @@ impl Build {
.env("RUSTDOC_REAL", self.rustdoc(compiler))
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));

self.add_bootstrap_key(compiler, &mut cargo);
self.add_bootstrap_key(&mut cargo);

// Specify some various options for build scripts used throughout
// the build.
@@ -862,16 +862,11 @@ impl Build {
}

/// Adds the compiler's bootstrap key to the environment of `cmd`.
fn add_bootstrap_key(&self, compiler: &Compiler, cmd: &mut Command) {
// In stage0 we're using a previously released stable compiler, so we
// use the stage0 bootstrap key. Otherwise we use our own build's
// bootstrap key.
let bootstrap_key = if compiler.is_snapshot(self) && !self.local_rebuild {
&self.bootstrap_key_stage0
} else {
&self.bootstrap_key
};
cmd.env("RUSTC_BOOTSTRAP_KEY", bootstrap_key);
fn add_bootstrap_key(&self, cmd: &mut Command) {
cmd.env("RUSTC_BOOTSTRAP", "");
// FIXME: Transitionary measure to bootstrap using the old bootstrap logic.
// Remove this once the bootstrap compiler uses the new login in Issue #36548.
cmd.env("RUSTC_BOOTSTRAP_KEY", "5c6cf767");
}

/// Returns the compiler's libdir where it stores the dynamic libraries that
5 changes: 2 additions & 3 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
@@ -1131,8 +1131,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
Adt(adt_def, variant, substs, _) => {
let variant_def = &adt_def.variants[variant];

ppaux::parameterized(fmt, substs, variant_def.did,
ppaux::Ns::Value, &[])?;
ppaux::parameterized(fmt, substs, variant_def.did, &[])?;

match variant_def.kind {
ty::VariantKind::Unit => Ok(()),
@@ -1227,7 +1226,7 @@ impl<'tcx> Debug for Literal<'tcx> {
use self::Literal::*;
match *self {
Item { def_id, substs } => {
ppaux::parameterized(fmt, substs, def_id, ppaux::Ns::Value, &[])
ppaux::parameterized(fmt, substs, def_id, &[])
}
Value { ref value } => {
write!(fmt, "const ")?;
2 changes: 1 addition & 1 deletion src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
@@ -336,7 +336,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
self.infcx.tcx
}

pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'tcx> {
pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
self.infcx.param_env()
}

16 changes: 8 additions & 8 deletions src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
@@ -148,6 +148,8 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl1_def_id: DefId,
impl2_def_id: DefId) -> bool {
debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);

if let Some(r) = tcx.specializes_cache.borrow().check(impl1_def_id, impl2_def_id) {
return r;
}
@@ -177,21 +179,22 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

// create a parameter environment corresponding to a (skolemized) instantiation of impl1
let mut penv = tcx.construct_parameter_environment(DUMMY_SP,
impl1_def_id,
region::DUMMY_CODE_EXTENT);
let penv = tcx.construct_parameter_environment(DUMMY_SP,
impl1_def_id,
region::DUMMY_CODE_EXTENT);
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
.unwrap()
.subst(tcx, &penv.free_substs);

let result = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|mut infcx| {
// Create a infcx, taking the predicates of impl1 as assumptions:
let result = tcx.infer_ctxt(None, Some(penv), Reveal::ExactMatch).enter(|mut infcx| {
// Normalize the trait reference, adding any obligations
// that arise into the impl1 assumptions.
let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = {
let selcx = &mut SelectionContext::new(&infcx);
traits::normalize(selcx, ObligationCause::dummy(), &impl1_trait_ref)
};
penv.caller_bounds.extend(normalization_obligations.into_iter().map(|o| {
infcx.parameter_environment.caller_bounds.extend(normalization_obligations.into_iter().map(|o| {
match tcx.lift_to_global(&o.predicate) {
Some(predicate) => predicate,
None => {
@@ -200,9 +203,6 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}));

// Install the parameter environment, taking the predicates of impl1 as assumptions:
infcx.parameter_environment = penv;

// Attempt to prove that impl2 applies, given all of the above.
fulfill_implication(&infcx, impl1_trait_ref, impl2_def_id).is_ok()
});
16 changes: 14 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ use util::nodemap::FnvHashMap;

use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
use std::cell::Cell;
use std::cell::{Cell, RefCell};
use std::hash::{Hash, Hasher};
use std::iter;
use std::ops::Deref;
@@ -1220,6 +1220,12 @@ pub struct ParameterEnvironment<'tcx> {
/// regions don't have this implicit scope and instead introduce
/// relationships in the environment.
pub free_id_outlive: CodeExtent,

/// A cache for `moves_by_default`.
pub is_copy_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,

/// A cache for `type_is_sized`
pub is_sized_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
}

impl<'a, 'tcx> ParameterEnvironment<'tcx> {
@@ -1232,6 +1238,8 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
implicit_region_bound: self.implicit_region_bound,
caller_bounds: caller_bounds,
free_id_outlive: self.free_id_outlive,
is_copy_cache: RefCell::new(FnvHashMap()),
is_sized_cache: RefCell::new(FnvHashMap()),
}
}

@@ -2782,7 +2790,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
free_substs: Substs::empty(self),
caller_bounds: Vec::new(),
implicit_region_bound: self.mk_region(ty::ReEmpty),
free_id_outlive: free_id_outlive
free_id_outlive: free_id_outlive,
is_copy_cache: RefCell::new(FnvHashMap()),
is_sized_cache: RefCell::new(FnvHashMap()),
}
}

@@ -2853,6 +2863,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
implicit_region_bound: tcx.mk_region(ty::ReScope(free_id_outlive)),
caller_bounds: predicates,
free_id_outlive: free_id_outlive,
is_copy_cache: RefCell::new(FnvHashMap()),
is_sized_cache: RefCell::new(FnvHashMap()),
};

let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps));
17 changes: 0 additions & 17 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
@@ -908,23 +908,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
}
}

impl<'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ParameterEnvironment {
free_substs: self.free_substs.fold_with(folder),
implicit_region_bound: self.implicit_region_bound.fold_with(folder),
caller_bounds: self.caller_bounds.fold_with(folder),
free_id_outlive: self.free_id_outlive,
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.free_substs.visit_with(visitor) ||
self.implicit_region_bound.visit_with(visitor) ||
self.caller_bounds.visit_with(visitor)
}
}

impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::error::ExpectedFound {
31 changes: 25 additions & 6 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
@@ -20,9 +20,11 @@ use ty::{Disr, ParameterEnvironment};
use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
use ty::TypeVariants::*;
use util::nodemap::FnvHashMap;

use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};

use std::cell::RefCell;
use std::cmp;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
@@ -579,11 +581,24 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
impl<'a, 'tcx> ty::TyS<'tcx> {
fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: &ParameterEnvironment<'tcx>,
bound: ty::BuiltinBound, span: Span) -> bool
bound: ty::BuiltinBound,
cache: &RefCell<FnvHashMap<Ty<'tcx>, bool>>,
span: Span) -> bool
{
tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch).enter(|infcx| {
traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span)
})
if self.has_param_types() || self.has_self_ty() {
if let Some(result) = cache.borrow().get(self) {
return *result;
}
}
let result =
tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch)
.enter(|infcx| {
traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span)
});
if self.has_param_types() || self.has_self_ty() {
cache.borrow_mut().insert(self, result);
}
return result;
}

// FIXME (@jroesch): I made this public to use it, not sure if should be private
@@ -610,7 +625,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
TyArray(..) | TySlice(..) | TyTrait(..) | TyTuple(..) |
TyClosure(..) | TyAdt(..) | TyAnon(..) |
TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
}.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
}.unwrap_or_else(|| {
!self.impls_bound(tcx, param_env, ty::BoundCopy, &param_env.is_copy_cache, span)
});

if !self.has_param_types() && !self.has_self_ty() {
self.flags.set(self.flags.get() | if result {
@@ -650,7 +667,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {

TyAdt(..) | TyProjection(..) | TyParam(..) |
TyInfer(..) | TyAnon(..) | TyError => None
}.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
}.unwrap_or_else(|| {
self.impls_bound(tcx, param_env, ty::BoundSized, &param_env.is_sized_cache, span)
});

if !self.has_param_types() && !self.has_self_ty() {
self.flags.set(self.flags.get() | if result {
69 changes: 49 additions & 20 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@

use hir::def_id::DefId;
use ty::subst::{self, Subst, Substs};
use hir::map::definitions::DefPathData;
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use ty::{TyBool, TyChar, TyAdt};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
@@ -56,35 +57,63 @@ fn fn_sig(f: &mut fmt::Formatter,
Ok(())
}

/// Namespace of the path given to parameterized to print.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Ns {
Type,
Value
}

pub fn parameterized(f: &mut fmt::Formatter,
substs: &subst::Substs,
did: DefId,
ns: Ns,
mut did: DefId,
projections: &[ty::ProjectionPredicate])
-> fmt::Result {
let key = ty::tls::with(|tcx| tcx.def_key(did));
let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() {
Some(name)
} else {
did.index = key.parent.unwrap_or_else(
|| bug!("finding type for {:?}, encountered def-id {:?} with no parent",
did, did));
parameterized(f, substs, did, projections)?;
return write!(f, "::{}", key.disambiguated_data.data.as_interned_str());
};

let mut verbose = false;
let mut num_supplied_defaults = 0;
let mut has_self = false;
let mut num_regions = 0;
let mut num_types = 0;
let mut item_name = None;
let mut is_value_path = false;
let fn_trait_kind = ty::tls::with(|tcx| {
let mut generics = tcx.lookup_generics(did);
// Unfortunately, some kinds of items (e.g., closures) don't have
// generics. So walk back up the find the closest parent that DOES
// have them.
let mut item_def_id = did;
loop {
let key = tcx.def_key(item_def_id);
match key.disambiguated_data.data {
DefPathData::TypeNs(_) => {
break;
}
DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => {
is_value_path = true;
break;
}
_ => {
// if we're making a symbol for something, there ought
// to be a value or type-def or something in there
// *somewhere*
item_def_id.index = key.parent.unwrap_or_else(|| {
bug!("finding type for {:?}, encountered def-id {:?} with no \
parent", did, item_def_id);
});
}
}
}
let mut generics = tcx.lookup_generics(item_def_id);
let mut path_def_id = did;
verbose = tcx.sess.verbose();
has_self = generics.has_self;

let mut child_types = 0;
if let Some(def_id) = generics.parent {
// Methods.
assert_eq!(ns, Ns::Value);
assert!(is_value_path);
child_types = generics.types.len();
generics = tcx.lookup_generics(def_id);
num_regions = generics.regions.len();
@@ -94,10 +123,11 @@ pub fn parameterized(f: &mut fmt::Formatter,
write!(f, "<{} as ", substs.type_at(0))?;
}

item_name = Some(tcx.item_name(did));
path_def_id = def_id;
} else {
if ns == Ns::Value {
item_name = None;

if is_value_path {
// Functions.
assert_eq!(has_self, false);
} else {
@@ -192,7 +222,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
start_or_continue(f, "", ">")?;

// For values, also print their name and type parameters.
if ns == Ns::Value {
if is_value_path {
empty.set(true);

if has_self {
@@ -298,7 +328,6 @@ impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self;
parameterized(f, trait_ref.substs,
trait_ref.def_id,
Ns::Type,
projection_bounds)
}
}
@@ -398,7 +427,7 @@ impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
let trait_ref = tcx.lift(&ty::Binder(*self))
.expect("could not lift TraitRef for printing")
.with_self_ty(tcx, dummy_self).0;
parameterized(f, trait_ref.substs, trait_ref.def_id, Ns::Type, &[])
parameterized(f, trait_ref.substs, trait_ref.def_id, &[])
})
}
}
@@ -798,7 +827,7 @@ impl<'tcx> fmt::Display for ty::Binder<ty::OutlivesPredicate<&'tcx ty::Region,

impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
parameterized(f, self.substs, self.def_id, Ns::Type, &[])
parameterized(f, self.substs, self.def_id, &[])
}
}

@@ -851,7 +880,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
}

write!(f, "{} {{", bare_fn.sig.0)?;
parameterized(f, substs, def_id, Ns::Value, &[])?;
parameterized(f, substs, def_id, &[])?;
write!(f, "}}")
}
TyFnPtr(ref bare_fn) => {
@@ -874,7 +903,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
!tcx.tcache.borrow().contains_key(&def.did) {
write!(f, "{}<..>", tcx.item_path_str(def.did))
} else {
parameterized(f, substs, def.did, Ns::Type, &[])
parameterized(f, substs, def.did, &[])
}
})
}
4 changes: 4 additions & 0 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
@@ -1106,6 +1106,10 @@ impl<'a, 'tcx> CrateMetadata {
}

fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, fm2: &syntax_pos::FileMap) -> bool {
if fm1.byte_length() != fm2.byte_length() {
return false;
}

if fm1.name != fm2.name {
return false;
}
32 changes: 13 additions & 19 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
use syntax::ext::base::MultiItemModifier;
use syntax::ext::hygiene::Mark;
use syntax::ast::{self, FloatTy};
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy};
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, SpannedIdent, IntTy, UintTy};
use syntax::parse::token::{self, keywords};
use syntax::util::lev_distance::find_best_match_for_name;

@@ -2237,7 +2237,7 @@ impl<'a> Resolver<'a> {
}

fn fresh_binding(&mut self,
ident: &ast::SpannedIdent,
ident: &SpannedIdent,
pat_id: NodeId,
outer_pat_id: NodeId,
pat_src: PatternSource,
@@ -2803,11 +2803,11 @@ impl<'a> Resolver<'a> {
} SuggestionType::NotFound
}

fn resolve_labeled_block(&mut self, label: Option<ast::Ident>, id: NodeId, block: &Block) {
fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) {
if let Some(label) = label {
let def = Def::Label(id);
self.with_label_rib(|this| {
this.label_ribs.last_mut().unwrap().bindings.insert(label, def);
this.label_ribs.last_mut().unwrap().bindings.insert(label.node, def);
this.visit_block(block);
});
} else {
@@ -3006,19 +3006,6 @@ impl<'a> Resolver<'a> {
visit::walk_expr(self, expr);
}

ExprKind::Loop(_, Some(label)) | ExprKind::While(.., Some(label)) => {
self.with_label_rib(|this| {
let def = Def::Label(expr.id);

{
let rib = this.label_ribs.last_mut().unwrap();
rib.bindings.insert(label.node, def);
}

visit::walk_expr(this, expr);
})
}

ExprKind::Break(Some(label)) | ExprKind::Continue(Some(label)) => {
match self.search_label(label.node) {
None => {
@@ -3048,12 +3035,19 @@ impl<'a> Resolver<'a> {
optional_else.as_ref().map(|expr| self.visit_expr(expr));
}

ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),

ExprKind::While(ref subexpression, ref block, label) => {
self.visit_expr(subexpression);
self.resolve_labeled_block(label, expr.id, &block);
}

ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
self.visit_expr(subexpression);
self.value_ribs.push(Rib::new(NormalRibKind));
self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FnvHashMap());

self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
self.resolve_labeled_block(label, expr.id, block);

self.value_ribs.pop();
}
@@ -3063,7 +3057,7 @@ impl<'a> Resolver<'a> {
self.value_ribs.push(Rib::new(NormalRibKind));
self.resolve_pattern(pattern, PatternSource::For, &mut FnvHashMap());

self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
self.resolve_labeled_block(label, expr.id, block);

self.value_ribs.pop();
}
2 changes: 1 addition & 1 deletion src/librustc_trans/monomorphize.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ pub struct Instance<'tcx> {

impl<'tcx> fmt::Display for Instance<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[])
ppaux::parameterized(f, &self.substs, self.def, &[])
}
}

2 changes: 1 addition & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -1458,7 +1458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}

pub fn param_env(&self) -> &ty::ParameterEnvironment<'tcx> {
pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
&self.parameter_environment
}

15 changes: 6 additions & 9 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -1296,15 +1296,12 @@ impl UnstableFeatures {
pub fn from_environment() -> UnstableFeatures {
// Whether this is a feature-staged build, i.e. on the beta or stable channel
let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
// The secret key needed to get through the rustc build itself by
// subverting the unstable features lints
let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY");
// The matching key to the above, only known by the build system
let bootstrap_provided_key = env::var("RUSTC_BOOTSTRAP_KEY").ok();
match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) {
(_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat,
(true, _, _) => UnstableFeatures::Disallow,
(false, _, _) => UnstableFeatures::Allow
// Whether we should enable unstable features for bootstrapping
let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
match (disable_unstable_features, bootstrap) {
(_, true) => UnstableFeatures::Cheat,
(true, _) => UnstableFeatures::Disallow,
(false, _) => UnstableFeatures::Allow
}
}

3 changes: 3 additions & 0 deletions src/libsyntax_pos/lib.rs
Original file line number Diff line number Diff line change
@@ -481,6 +481,9 @@ impl FileMap {
self.src.is_none()
}

pub fn byte_length(&self) -> u32 {
self.end_pos.0 - self.start_pos.0
}
pub fn count_lines(&self) -> usize {
self.lines.borrow().len()
}
1 change: 0 additions & 1 deletion src/stage0.txt
Original file line number Diff line number Diff line change
@@ -13,5 +13,4 @@
# released on `$date`

rustc: 1.12.1-2016-10-20
rustc_key: 5c6cf767
cargo: nightly-2016-08-21
3 changes: 3 additions & 0 deletions src/test/compile-fail/resolve-label.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,9 @@ fn f() {
}
}
}

// issue #37353
loop { 'w: while break 'w { } } //~ ERROR use of undeclared label
}

fn main() {}
52 changes: 52 additions & 0 deletions src/test/run-pass/issue-37291/auxiliary/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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.

#![crate_type = "lib"]

use std::ops::Mul;

pub trait A {}
pub trait B {
type AT: A;
}
pub trait C {
type BT: B;
}

pub struct AV;
impl A for AV {}

pub struct BV;
impl B for BV {
type AT = AV;
}

pub struct CV;
impl C for CV {
type BT = BV;
}

pub struct WrapperB<T>(pub T);
pub struct WrapperC<T>(pub T);

impl<C1> Mul<WrapperB<<C1::BT as B>::AT>> for WrapperC<C1>
where C1: C
{
type Output = u8;
fn mul(self, _: WrapperB<<C1::BT as B>::AT>) -> Self::Output {
loop {}
}
}
impl<C1> Mul<WrapperC<C1>> for WrapperC<C1> {
type Output = u8;
fn mul(self, _: WrapperC<C1>) -> Self::Output {
loop {}
}
}
29 changes: 29 additions & 0 deletions src/test/run-pass/issue-37291/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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.

// aux-build:lib.rs

// Regression test for #37291. The problem was that the starting
// environment for a specialization check was not including the
// where-clauses from the impl when attempting to normalize the impl's
// trait-ref, so things like `<C as Foo>::Item` could not resolve,
// since the `C: Foo` trait bound was not included in the environment.

extern crate lib;

use lib::{CV, WrapperB, WrapperC};

fn main() {
let a = WrapperC(CV);
let b = WrapperC(CV);
if false {
let _ = a * b;
}
}