Skip to content

Commit

Permalink
Auto merge of rust-lang#57305 - pietroalbini:beta-rollup, r=pietroalbini
Browse files Browse the repository at this point in the history
[beta] Rollup backports

Cherry-picked:

* rust-lang#57053: Fix alignment for array indexing
* rust-lang#57181: resolve: Fix another ICE in import validation
* rust-lang#57185: resolve: Fix one more ICE in import validation
* rust-lang#57282: Wf-check the output type of a function in MIR-typeck
* rust-lang#55318: Ensure that Rustdoc discovers all necessary auto trait bounds
* rust-lang#56838: Call poly_project_and_unify_type on types that contain inference types

Rolled up:

* rust-lang#57300: [beta] Update RLS to include 100% CPU on hover bugfix
* rust-lang#57301: beta: bootstrap from latest stable (1.31.1)
* rust-lang#57292: [BETA] Update cargo

r? @ghost
  • Loading branch information
bors committed Jan 4, 2019
2 parents fa64cc8 + 443165d commit e64fee6
Show file tree
Hide file tree
Showing 24 changed files with 375 additions and 57 deletions.
98 changes: 81 additions & 17 deletions src/librustc/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
continue;
}

let result = select.select(&Obligation::new(dummy_cause.clone(), new_env, pred));
// Call infcx.resolve_type_vars_if_possible to see if we can
// get rid of any inference variables.
let obligation = infcx.resolve_type_vars_if_possible(
&Obligation::new(dummy_cause.clone(), new_env, pred)
);
let result = select.select(&obligation);

match &result {
&Ok(Some(ref vtable)) => {
Expand Down Expand Up @@ -369,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}
&Ok(None) => {}
&Err(SelectionError::Unimplemented) => {
if self.is_of_param(pred.skip_binder().trait_ref.substs) {
if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
already_visited.remove(&pred);
self.add_user_pred(
&mut user_computed_preds,
Expand Down Expand Up @@ -631,18 +636,28 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
finished_map
}

pub fn is_of_param(&self, substs: &Substs<'_>) -> bool {
if substs.is_noop() {
return false;
}
fn is_param_no_infer(&self, substs: &Substs<'_>) -> bool {
return self.is_of_param(substs.type_at(0)) &&
!substs.types().any(|t| t.has_infer_types());
}

return match substs.type_at(0).sty {
pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
return match ty.sty {
ty::Param(_) => true,
ty::Projection(p) => self.is_of_param(p.substs),
ty::Projection(p) => self.is_of_param(p.self_ty()),
_ => false,
};
}

fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
match p.ty().skip_binder().sty {
ty::Projection(proj) if proj == p.skip_binder().projection_ty => {
true
},
_ => false
}
}

pub fn evaluate_nested_obligations<
'b,
'c,
Expand All @@ -661,28 +676,77 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
) -> bool {
let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);

for (obligation, predicate) in nested
.filter(|o| o.recursion_depth == 1)
for (obligation, mut predicate) in nested
.map(|o| (o.clone(), o.predicate.clone()))
{
let is_new_pred =
fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone()));

// Resolve any inference variables that we can, to help selection succeed
predicate = select.infcx().resolve_type_vars_if_possible(&predicate);

// We only add a predicate as a user-displayable bound if
// it involves a generic parameter, and doesn't contain
// any inference variables.
//
// Displaying a bound involving a concrete type (instead of a generic
// parameter) would be pointless, since it's always true
// (e.g. u8: Copy)
// Displaying an inference variable is impossible, since they're
// an internal compiler detail without a defined visual representation
//
// We check this by calling is_of_param on the relevant types
// from the various possible predicates
match &predicate {
&ty::Predicate::Trait(ref p) => {
let substs = &p.skip_binder().trait_ref.substs;
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
&& !only_projections
&& is_new_pred {

if self.is_of_param(substs) && !only_projections && is_new_pred {
self.add_user_pred(computed_preds, predicate);
}
predicates.push_back(p.clone());
}
&ty::Predicate::Projection(p) => {
// If the projection isn't all type vars, then
// we don't want to add it as a bound
if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred {
self.add_user_pred(computed_preds, predicate);
} else {
debug!("evaluate_nested_obligations: examining projection predicate {:?}",
predicate);

// As described above, we only want to display
// bounds which include a generic parameter but don't include
// an inference variable.
// Additionally, we check if we've seen this predicate before,
// to avoid rendering duplicate bounds to the user.
if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
&& !p.ty().skip_binder().is_ty_infer()
&& is_new_pred {
debug!("evaluate_nested_obligations: adding projection predicate\
to computed_preds: {:?}", predicate);

// Under unusual circumstances, we can end up with a self-refeential
// projection predicate. For example:
// <T as MyType>::Value == <T as MyType>::Value
// Not only is displaying this to the user pointless,
// having it in the ParamEnv will cause an issue if we try to call
// poly_project_and_unify_type on the predicate, since this kind of
// predicate will normally never end up in a ParamEnv.
//
// For these reasons, we ignore these weird predicates,
// ensuring that we're able to properly synthesize an auto trait impl
if self.is_self_referential_projection(p) {
debug!("evaluate_nested_obligations: encountered a projection
predicate equating a type with itself! Skipping");

} else {
self.add_user_pred(computed_preds, predicate);
}
}

// We can only call poly_project_and_unify_type when our predicate's
// Ty contains an inference variable - otherwise, there won't be anything to
// unify
if p.ty().skip_binder().has_infer_types() {
debug!("Projecting and unifying projection predicate {:?}",
predicate);
match poly_project_and_unify_type(select, &obligation.with(p.clone())) {
Err(e) => {
debug!(
Expand Down
13 changes: 11 additions & 2 deletions src/librustc_codegen_ssa/mir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
bx: &mut Bx,
llindex: V
) -> Self {
// Statically compute the offset if we can, otherwise just use the element size,
// as this will yield the lowest alignment.
let layout = self.layout.field(bx, 0);
let offset = if bx.is_const_integral(llindex) {
layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size)
} else {
layout.size
};

PlaceRef {
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
llextra: None,
layout: self.layout.field(bx.cx(), 0),
align: self.align
layout,
align: self.align.restrict_for_offset(offset),
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());

let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size);
cg_elem.val.store(&mut body_bx,
PlaceRef::new_sized(current, cg_elem.layout, dest.align));
PlaceRef::new_sized(current, cg_elem.layout, align));

let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]);
body_bx.br(header_bx.llbb());
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
self.check_call_dest(mir, term, &sig, destination, term_location);

self.prove_predicates(
sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
sig.inputs_and_output.iter().map(|ty| ty::Predicate::WellFormed(ty)),
term_location.to_locations(),
ConstraintCategory::Boring,
);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
type MemoryExtra: Default;

/// Extra data stored in every allocation.
type AllocExtra: AllocationExtra<Self::PointerTag, Self::MemoryExtra>;
type AllocExtra: AllocationExtra<Self::PointerTag, Self::MemoryExtra> + 'static;

/// Memory's allocation map
type MemoryMap:
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1022,11 +1022,11 @@ enum ModuleOrUniformRoot<'a> {
CurrentScope,
}

impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
fn eq(&self, other: &Self) -> bool {
match (*self, *other) {
impl ModuleOrUniformRoot<'_> {
fn same_def(lhs: Self, rhs: Self) -> bool {
match (lhs, rhs) {
(ModuleOrUniformRoot::Module(lhs),
ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs),
ModuleOrUniformRoot::Module(rhs)) => lhs.def() == rhs.def(),
(ModuleOrUniformRoot::CrateRootAndExternPrelude,
ModuleOrUniformRoot::CrateRootAndExternPrelude) |
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) |
Expand Down
8 changes: 7 additions & 1 deletion src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,10 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
self.set_binding_parent_module(binding, module);
self.update_resolution(module, ident, ns, |this, resolution| {
if let Some(old_binding) = resolution.binding {
if binding.def() == Def::Err {
// Do not override real bindings with `Def::Err`s from error recovery.
return Ok(());
}
match (old_binding.is_glob_import(), binding.is_glob_import()) {
(true, true) => {
if binding.def() != old_binding.def() {
Expand Down Expand Up @@ -836,7 +840,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
if let Some(initial_module) = directive.imported_module.get() {
if module != initial_module && self.ambiguity_errors.is_empty() {
if !ModuleOrUniformRoot::same_def(module, initial_module)
&& self.ambiguity_errors.is_empty()
{
span_bug!(directive.span, "inconsistent resolution for an import");
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/stage0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.

date: 2018-12-06
rustc: 1.31.0
date: 2018-12-20
rustc: 1.31.1
cargo: 0.32.0

# When making a stable release the process currently looks like:
Expand Down
44 changes: 44 additions & 0 deletions src/test/codegen/issue-56927.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// compile-flags: -C no-prepopulate-passes

#![crate_type="rlib"]
use std::usize;

#[repr(align(16))]
pub struct S {
arr: [u32; 4],
}

// CHECK-LABEL: @test1
// CHECK: store i32 0, i32* %{{.+}}, align 16
// CHECK: store i32 1, i32* %{{.+}}, align 4
// CHECK: store i32 2, i32* %{{.+}}, align 8
// CHECK: store i32 3, i32* %{{.+}}, align 4
#[no_mangle]
pub fn test1(s: &mut S) {
s.arr[0] = 0;
s.arr[1] = 1;
s.arr[2] = 2;
s.arr[3] = 3;
}

// CHECK-LABEL: @test2
// CHECK: store i32 4, i32* %{{.+}}, align 4
#[allow(const_err)]
#[no_mangle]
pub fn test2(s: &mut S) {
s.arr[usize::MAX / 4 + 1] = 4;
}

// CHECK-LABEL: @test3
// CHECK: store i32 5, i32* %{{.+}}, align 4
#[no_mangle]
pub fn test3(s: &mut S, i: usize) {
s.arr[i] = 5;
}

// CHECK-LABEL: @test4
// CHECK: store i32 6, i32* %{{.+}}, align 4
#[no_mangle]
pub fn test4(s: &mut S) {
s.arr = [6; 4];
}
36 changes: 36 additions & 0 deletions src/test/codegen/packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,42 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
BigPacked2 { dealign: 0, data: f() }
}

// CHECK-LABEL: @write_packed_array1
// CHECK: store i32 0, i32* %{{.+}}, align 1
// CHECK: store i32 1, i32* %{{.+}}, align 1
// CHECK: store i32 2, i32* %{{.+}}, align 1
#[no_mangle]
pub fn write_packed_array1(p: &mut BigPacked1) {
p.data.0[0] = 0;
p.data.0[1] = 1;
p.data.0[2] = 2;
}

// CHECK-LABEL: @write_packed_array2
// CHECK: store i32 0, i32* %{{.+}}, align 2
// CHECK: store i32 1, i32* %{{.+}}, align 2
// CHECK: store i32 2, i32* %{{.+}}, align 2
#[no_mangle]
pub fn write_packed_array2(p: &mut BigPacked2) {
p.data.0[0] = 0;
p.data.0[1] = 1;
p.data.0[2] = 2;
}

// CHECK-LABEL: @repeat_packed_array1
// CHECK: store i32 42, i32* %{{.+}}, align 1
#[no_mangle]
pub fn repeat_packed_array1(p: &mut BigPacked1) {
p.data.0 = [42; 8];
}

// CHECK-LABEL: @repeat_packed_array2
// CHECK: store i32 42, i32* %{{.+}}, align 2
#[no_mangle]
pub fn repeat_packed_array2(p: &mut BigPacked2) {
p.data.0 = [42; 8];
}

#[repr(packed)]
#[derive(Copy, Clone)]
pub struct Packed1Pair(u8, u32);
Expand Down
31 changes: 31 additions & 0 deletions src/test/rustdoc/issue-50159.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 trait Signal {
type Item;
}

pub trait Signal2 {
type Item2;
}

impl<B, C> Signal2 for B where B: Signal<Item = C> {
type Item2 = C;
}

// @has issue_50159/struct.Switch.html
// @has - '//code' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send'
// @has - '//code' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync'
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0
// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 2
pub struct Switch<B: Signal> {
pub inner: <B as Signal2>::Item2,
}
Loading

0 comments on commit e64fee6

Please sign in to comment.