// default values for all options that we haven't otherwise stored yet.
set(&mut config.initial_rustc, build.rustc.map(PathBuf::from));
- set(&mut config.initial_rustc, build.cargo.map(PathBuf::from));
+ set(&mut config.initial_cargo, build.cargo.map(PathBuf::from));
let default = false;
config.llvm_assertions = llvm_assertions.unwrap_or(default);
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) {
AllocDiscriminant::Alloc.hash_stable(hcx, hasher);
- if !hcx.alloc_id_recursion_tracker.insert(*self) {
+ if hcx.alloc_id_recursion_tracker.insert(*self) {
tcx
.interpret_interner
.get_corresponding_static_def_id(*self)
self.resolve_type_vars_or_error(expr.hir_id, self.tables.expr_ty_adjusted_opt(expr))
}
+ /// Returns the type of value that this pattern matches against.
+ /// Some non-obvious cases:
+ ///
+ /// - a `ref x` binding matches against a value of type `T` and gives
+ /// `x` the type `&T`; we return `T`.
+ /// - a pattern with implicit derefs (thanks to default binding
+ /// modes #42640) may look like `Some(x)` but in fact have
+ /// implicit deref patterns attached (e.g., it is really
+ /// `&Some(x)`). In that case, we return the "outermost" type
+ /// (e.g., `&Option<T>).
fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
+ // Check for implicit `&` types wrapping the pattern; note
+ // that these are never attached to binding patterns, so
+ // actually this is somewhat "disjoint" from the code below
+ // that aims to account for `ref x`.
+ if let Some(vec) = self.tables.pat_adjustments().get(pat.hir_id) {
+ if let Some(first_ty) = vec.first() {
+ debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
+ return Ok(first_ty);
+ }
+ }
+
+ self.pat_ty_unadjusted(pat)
+ }
+
+
+ /// Like `pat_ty`, but ignores implicit `&` patterns.
+ fn pat_ty_unadjusted(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
let base_ty = self.node_ty(pat.hir_id)?;
+ debug!("pat_ty(pat={:?}) base_ty={:?}", pat, base_ty);
+
// This code detects whether we are looking at a `ref x`,
// and if so, figures out what the type *being borrowed* is.
let ret_ty = match pat.node {
}
_ => base_ty,
};
- debug!("pat_ty(pat={:?}) base_ty={:?} ret_ty={:?}",
- pat, base_ty, ret_ty);
+ debug!("pat_ty(pat={:?}) ret_ty={:?}", pat, ret_ty);
+
Ok(ret_ty)
}
self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
}
Def::StructCtor(_, CtorKind::Fn) => {
- match self.pat_ty(&pat)?.sty {
+ match self.pat_ty_unadjusted(&pat)?.sty {
ty::TyAdt(adt_def, _) => {
(cmt, adt_def.non_enum_variant().fields.len())
}
PatKind::Tuple(ref subpats, ddpos) => {
// (p1, ..., pN)
- let expected_len = match self.pat_ty(&pat)?.sty {
+ let expected_len = match self.pat_ty_unadjusted(&pat)?.sty {
ty::TyTuple(ref tys) => tys.len(),
ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
};
if self.can_use_global_caches(param_env) {
let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
+ debug!(
+ "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
+ trait_ref,
+ result,
+ );
cache.insert(trait_ref, WithDepNode::new(dep_node, result));
return;
}
}
+ debug!(
+ "insert_evaluation_cache(trait_ref={:?}, candidate={:?})",
+ trait_ref,
+ result,
+ );
self.infcx.evaluation_cache.hashmap
.borrow_mut()
.insert(trait_ref, WithDepNode::new(dep_node, result));
if self.intercrate_ambiguity_causes.is_some() {
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
// Heuristics: show the diagnostics when there are no candidates in crate.
- let candidate_set = self.assemble_candidates(stack)?;
- if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
- !self.evaluate_candidate(stack, &c).may_apply()
- }) {
- let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
- let self_ty = trait_ref.self_ty();
- let trait_desc = trait_ref.to_string();
- let self_desc = if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- };
- let cause = if let Conflict::Upstream = conflict {
- IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
- } else {
- IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
- };
- debug!("evaluate_stack: pushing cause = {:?}", cause);
- self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+ if let Ok(candidate_set) = self.assemble_candidates(stack) {
+ if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
+ !self.evaluate_candidate(stack, &c).may_apply()
+ }) {
+ let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+ let self_ty = trait_ref.self_ty();
+ let trait_desc = trait_ref.to_string();
+ let self_desc = if self_ty.has_concrete_skeleton() {
+ Some(self_ty.to_string())
+ } else {
+ None
+ };
+ let cause = if let Conflict::Upstream = conflict {
+ IntercrateAmbiguityCause::UpstreamCrateUpdate {
+ trait_desc,
+ self_desc,
+ }
+ } else {
+ IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+ };
+ debug!("evaluate_stack: pushing cause = {:?}", cause);
+ self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+ }
}
}
return Ok(None);
let mut cache = tcx.selection_cache.hashmap.borrow_mut();
if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
if let Some(candidate) = tcx.lift_to_global(&candidate) {
+ debug!(
+ "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
+ trait_ref,
+ candidate,
+ );
cache.insert(trait_ref, WithDepNode::new(dep_node, candidate));
return;
}
}
}
+ debug!(
+ "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
+ trait_ref,
+ candidate,
+ );
self.infcx.selection_cache.hashmap
.borrow_mut()
.insert(trait_ref, WithDepNode::new(dep_node, candidate));
}
- pub(crate) fn write_discriminant_value(
+ pub fn write_discriminant_value(
&mut self,
dest_ty: Ty<'tcx>,
dest: Place,
_ => t.super_visit_with(self)
}
}
+
+ fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {
+ true
+ }
}
let mut param_count = CountParams { params: FxHashSet() };
- pred.visit_with(&mut param_count);
+ let has_region = pred.visit_with(&mut param_count);
let substituted_pred = pred.subst(fcx.tcx, substs);
- // Don't check non-defaulted params, dependent defaults or preds with multiple params.
- if substituted_pred.references_error() || param_count.params.len() > 1 {
+ // Don't check non-defaulted params, dependent defaults (including lifetimes)
+ // or preds with multiple params.
+ if substituted_pred.references_error() || param_count.params.len() > 1
+ || has_region {
continue;
}
// Avoid duplication of predicates that contain no parameters, for example.
--- /dev/null
+// Copyright 2018 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.
+
+pub const A: &str = "hello";
--- /dev/null
+// Copyright 2018 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.
+
+pub const A: &str = "xxxxx";
--- /dev/null
+// Copyright 2018 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.
+
+// revisions:cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph --test
+// must-compile-successfully
+
+#![feature(rustc_attrs)]
+#![crate_type = "rlib"]
+
+#![rustc_partition_translated(module="issue_49595-tests", cfg="cfail2")]
+#![rustc_partition_translated(module="issue_49595-lit_test", cfg="cfail3")]
+
+mod tests {
+ #[cfg_attr(not(cfail1), ignore)]
+ #[test]
+ fn test() {
+ }
+}
+
+
+// Checks that changing a string literal without changing its span
+// takes effect.
+
+// replacing a module to have a stable span
+#[cfg_attr(not(cfail3), path = "auxiliary/lit_a.rs")]
+#[cfg_attr(cfail3, path = "auxiliary/lit_b.rs")]
+mod lit;
+
+pub mod lit_test {
+ #[test]
+ fn lit_test() {
+ println!("{}", ::lit::A);
+ }
+}
// Not even for well-formedness.
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
+// Issue #49344, predicates with lifetimes should not be checked.
+trait Scope<'a> {}
+struct Request<'a, S: Scope<'a> = i32>(S, &'a ());
+
fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+// Regression test for #48728, an ICE that occurred computing
+// coherence "help" information.
+
+#[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
+struct Node<T: ?Sized>(Box<T>);
+
+impl<T: Clone + ?Sized> Clone for Node<[T]> {
+ fn clone(&self) -> Self {
+ Node(Box::clone(&self.0))
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Node<[_]>`:
+ --> $DIR/issue-48728.rs:14:10
+ |
+LL | #[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
+ | ^^^^^ conflicting implementation for `Node<[_]>`
+...
+LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
+ | ------------------------------------------- first implementation here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
--- /dev/null
+// 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 <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.
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Foo {
+}
+
+impl Foo {
+ fn get(&self) -> Option<&Result<String, String>> {
+ None
+ }
+
+ fn mutate(&mut self) { }
+}
+
+fn main() {
+ let mut foo = Foo { };
+
+ // foo.get() returns type Option<&Result<String, String>>, so
+ // using `string` keeps borrow of `foo` alive. Hence calling
+ // `foo.mutate()` should be an error.
+ while let Some(Ok(string)) = foo.get() {
+ foo.mutate();
+ //~^ ERROR cannot borrow `foo` as mutable
+ println!("foo={:?}", *string);
+ }
+}
--- /dev/null
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+ --> $DIR/borrowck-issue-49631.rs:30:9
+ |
+LL | while let Some(Ok(string)) = foo.get() {
+ | --- - immutable borrow ends here
+ | |
+ | immutable borrow occurs here
+LL | foo.mutate();
+ | ^^^ mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.