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

Rollup of 5 pull requests #55230

Merged
merged 8 commits into from
Oct 21, 2018
2 changes: 1 addition & 1 deletion src/doc/book
Submodule book updated 26 files
+1 −1 2018-edition/book.toml
+5 −4 2018-edition/src/SUMMARY.md
+79 −0 2018-edition/src/appendix-07-other-useful-tools.md
+58 −0 2018-edition/src/appendix-08-editions.md
+1 −1 2018-edition/src/ch00-00-introduction.md
+4 −2 2018-edition/src/ch01-03-hello-cargo.md
+4 −3 2018-edition/src/ch02-00-guessing-game-tutorial.md
+43 −9 2018-edition/src/ch03-00-common-programming-concepts.md
+21 −17 2018-edition/src/ch04-02-references-and-borrowing.md
+12 −9 2018-edition/src/ch04-03-slices.md
+0 −24 2018-edition/src/ch07-00-modules.md
+15 −0 2018-edition/src/ch07-00-packages-crates-and-modules.md
+0 −480 2018-edition/src/ch07-01-mod-and-the-filesystem.md
+46 −0 2018-edition/src/ch07-01-packages-and-crates-for-making-libraries-and-executables.md
+0 −288 2018-edition/src/ch07-02-controlling-visibility-with-pub.md
+579 −0 2018-edition/src/ch07-02-modules-and-use-to-control-scope-and-privacy.md
+0 −304 2018-edition/src/ch07-03-importing-names-with-use.md
+12 −10 2018-edition/src/ch08-01-vectors.md
+22 −10 2018-edition/src/ch09-02-recoverable-errors-with-result.md
+18 −7 2018-edition/src/ch10-02-traits.md
+2 −0 2018-edition/src/ch10-03-lifetime-syntax.md
+1 −1 2018-edition/src/ch11-01-writing-tests.md
+3 −3 2018-edition/src/ch12-03-improving-error-handling-and-modularity.md
+19 −0 2018-edition/src/ch19-05-advanced-functions-and-closures.md
+528 −0 2018-edition/src/ch19-06-macros.md
+9 −0 2018-edition/src/theme/2018-edition.css
2 changes: 1 addition & 1 deletion src/doc/nomicon
2 changes: 1 addition & 1 deletion src/doc/reference
2 changes: 1 addition & 1 deletion src/doc/rust-by-example
12 changes: 5 additions & 7 deletions src/librustc_codegen_llvm/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ impl LtoModuleCodegen {
let module = module.take().unwrap();
{
let config = cgcx.config(module.kind);
let llmod = module.module_llvm.llmod();
let tm = &*module.module_llvm.tm;
run_pass_manager(cgcx, tm, llmod, config, false);
run_pass_manager(cgcx, &module, config, false);
timeline.record("fat-done");
}
Ok(module)
Expand Down Expand Up @@ -557,8 +555,7 @@ fn thin_lto(cgcx: &CodegenContext,
}

fn run_pass_manager(cgcx: &CodegenContext,
tm: &llvm::TargetMachine,
llmod: &llvm::Module,
module: &ModuleCodegen,
config: &ModuleConfig,
thin: bool) {
// Now we have one massive module inside of llmod. Time to run the
Expand All @@ -569,7 +566,8 @@ fn run_pass_manager(cgcx: &CodegenContext,
debug!("running the pass manager");
unsafe {
let pm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
let llmod = module.module_llvm.llmod();
llvm::LLVMRustAddAnalysisPasses(module.module_llvm.tm, pm, llmod);

if config.verify_llvm_ir {
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
Expand Down Expand Up @@ -864,7 +862,7 @@ impl ThinModule {
// little differently.
info!("running thin lto passes over {}", module.name);
let config = cgcx.config(module.kind);
run_pass_manager(cgcx, module.module_llvm.tm, llmod, config, true);
run_pass_manager(cgcx, &module, config, true);
cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
timeline.record("thin-done");
}
Expand Down
34 changes: 33 additions & 1 deletion src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
None,
&format!("llvm module passes [{}]", module_name.unwrap()),
|| {
llvm::LLVMRunPassManager(mpm, llmod)
llvm::LLVMRunPassManager(mpm, llmod);
});

// Deallocate managers that we're now done with
Expand Down Expand Up @@ -691,6 +691,38 @@ unsafe fn codegen(cgcx: &CodegenContext,
create_msvc_imps(cgcx, llcx, llmod);
}

// Ok now this one's a super interesting invocations. SIMD in rustc is
// difficult where we want some parts of the program to be able to use
// some SIMD features while other parts of the program don't. The real
// tough part is that we want this to actually work correctly!
//
// We go to great lengths to make sure this works, and one crucial
// aspect is that vector arguments (simd types) are never passed by
// value in the ABI of functions. It turns out, however, that LLVM will
// undo our "clever work" of passing vector types by reference. Its
// argument promotion pass will promote these by-ref arguments to
// by-val. That, however, introduces codegen errors!
//
// The upstream LLVM bug [1] has unfortunatey not really seen a lot of
// activity. The Rust bug [2], however, has seen quite a lot of reports
// of this in the wild. As a result, this is worked around locally here.
// We have a custom transformation, `LLVMRustDemoteSimdArguments`, which
// does the opposite of argument promotion by demoting any by-value SIMD
// arguments in function signatures to pointers intead of being
// by-value.
//
// This operates at the LLVM IR layer because LLVM is thwarting our
// codegen and this is the only chance we get to make sure it's correct
// before we hit codegen.
//
// Hopefully one day the upstream LLVM bug will be fixed and we'll no
// longer need this!
//
// [1]: https://bugs.llvm.org/show_bug.cgi?id=37358
// [2]: https://github.com/rust-lang/rust/issues/50154
llvm::LLVMRustDemoteSimdArguments(llmod);
cgcx.save_temp_bitcode(&module, "simd-demoted");

// A codegen-specific pass manager is used to generate object
// files for an LLVM module.
//
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,8 @@ extern "C" {
/// Runs a pass manager on a module.
pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool;

pub fn LLVMRustDemoteSimdArguments(M: &'a Module);

pub fn LLVMInitializePasses();

pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ fn main() {
}

build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm"));
cfg.file("../rustllvm/PassWrapper.cpp")
cfg
.file("../rustllvm/DemoteSimd.cpp")
.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp")
.file("../rustllvm/Linker.cpp")
Expand Down
228 changes: 207 additions & 21 deletions src/librustc_traits/chalk_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ use rustc::traits::{
Goal,
GoalKind,
Clause,
ProgramClauseCategory,
QuantifierKind,
Environment,
InEnvironment,
};
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::subst::Kind;
use rustc::ty::{self, TyCtxt};
use rustc::hir::def_id::DefId;

use std::fmt::{self, Debug};
use std::marker::PhantomData;
Expand Down Expand Up @@ -330,46 +332,230 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
{
fn program_clauses(
&self,
_environment: &Environment<'tcx>,
environment: &Environment<'tcx>,
goal: &DomainGoal<'tcx>,
) -> Vec<Clause<'tcx>> {
use rustc::traits::WhereClause::*;

match goal {
DomainGoal::Holds(Implemented(_trait_predicate)) => {
fn assemble_clauses_from_impls<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
trait_def_id: DefId,
clauses: &mut Vec<Clause<'tcx>>
) {
tcx.for_each_impl(trait_def_id, |impl_def_id| {
clauses.extend(
tcx.program_clauses_for(impl_def_id)
.into_iter()
.cloned()
);
});
}

fn assemble_clauses_from_assoc_ty_values<'tcx>(
tcx: ty::TyCtxt<'_, '_, 'tcx>,
trait_def_id: DefId,
clauses: &mut Vec<Clause<'tcx>>
) {
tcx.for_each_impl(trait_def_id, |impl_def_id| {
for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
clauses.extend(
tcx.program_clauses_for(*def_id)
.into_iter()
.cloned()
);
}
});
}

let mut clauses = match goal {
DomainGoal::Holds(Implemented(trait_predicate)) => {
// These come from:
// * implementations of the trait itself (rule `Implemented-From-Impl`)
// * the trait decl (rule `Implemented-From-Env`)

let mut clauses = vec![];
assemble_clauses_from_impls(
self.infcx.tcx,
trait_predicate.def_id(),
&mut clauses
);

// FIXME: we need to add special rules for builtin impls:
// * `Copy` / `Clone`
// * `Sized`
// * `Unsize`
// * `Generator`
// * `FnOnce` / `FnMut` / `Fn`
// * trait objects
// * auto traits

// Rule `Implemented-From-Env` will be computed from the environment.
clauses
}

DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
// These come from:
// * the assoc type definition (rule `ProjectionEq-Placeholder`)
// * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)

let clauses = self.infcx.tcx.program_clauses_for(
projection_predicate.projection_ty.item_def_id
).into_iter()

// only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
.filter(|clause| clause.category() == ProgramClauseCategory::Other)

.cloned()
.collect::<Vec<_>>();

// Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
// from the environment.
clauses
}

DomainGoal::Holds(RegionOutlives(..)) => {
// These come from:
//
// - Trait definitions (implied bounds)
// - Implementations of the trait itself
panic!()
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)

// All of these rules are computed in the environment.
vec![]
}

DomainGoal::Holds(ProjectionEq(_projection_predicate)) => {
DomainGoal::Holds(TypeOutlives(..)) => {
// These come from:
panic!()
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)

// All of these rules are computed in the environment.
vec![]
}

DomainGoal::Holds(RegionOutlives(_region_outlives)) => {
panic!()
DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
// These come from -- the trait decl (rule `WellFormed-TraitRef`).
self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
.into_iter()

// only select `WellFormed-TraitRef`
.filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)

.cloned()
.collect()
}

DomainGoal::Holds(TypeOutlives(_type_outlives)) => {
panic!()
DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
// These come from:
// * the associated type definition if `ty` refers to an unnormalized
// associated type (rule `WellFormed-AssocTy`)
// * custom rules for built-in types
// * the type definition otherwise (rule `WellFormed-Type`)
let clauses = match ty.sty {
ty::Projection(data) => {
self.infcx.tcx.program_clauses_for(data.item_def_id)
}

// These types are always WF (recall that we do not check
// for parameters to be WF)
ty::Bool |
ty::Char |
ty::Int(..) |
ty::Uint(..) |
ty::Float(..) |
ty::Str |
ty::RawPtr(..) |
ty::FnPtr(..) |
ty::Param(..) |
ty::Never => {
ty::List::empty()
}

// WF if inner type is `Sized`
ty::Slice(..) |
ty::Array(..) => {
ty::List::empty()
}

ty::Tuple(..) => {
ty::List::empty()
}

// WF if `sub_ty` outlives `region`
ty::Ref(..) => {
ty::List::empty()
}

ty::Dynamic(..) => {
// FIXME: no rules yet for trait objects
ty::List::empty()
}

ty::Adt(def, ..) => {
self.infcx.tcx.program_clauses_for(def.did)
}

ty::Foreign(def_id) |
ty::FnDef(def_id, ..) |
ty::Closure(def_id, ..) |
ty::Generator(def_id, ..) |
ty::Opaque(def_id, ..) => {
self.infcx.tcx.program_clauses_for(def_id)
}

ty::GeneratorWitness(..) |
ty::UnnormalizedProjection(..) |
ty::Infer(..) |
ty::Error => {
bug!("unexpected type {:?}", ty)
}
};

clauses.into_iter()
.filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
.cloned()
.collect()
}

DomainGoal::WellFormed(WellFormed::Trait(_trait_predicate)) => {
// These come from -- the trait decl.
panic!()
DomainGoal::FromEnv(FromEnv::Trait(..)) => {
// These come from:
// * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
// * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
// * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
// `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)

// All of these rules are computed in the environment.
vec![]
}

DomainGoal::WellFormed(WellFormed::Ty(_ty)) => panic!(),
DomainGoal::FromEnv(FromEnv::Ty(..)) => {
// There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
// comes from the environment).
vec![]
}

DomainGoal::FromEnv(FromEnv::Trait(_trait_predicate)) => panic!(),
DomainGoal::Normalize(projection_predicate) => {
// These come from -- assoc ty values (rule `Normalize-From-Impl`).
let mut clauses = vec![];

DomainGoal::FromEnv(FromEnv::Ty(_ty)) => panic!(),
assemble_clauses_from_assoc_ty_values(
self.infcx.tcx,
projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
&mut clauses
);

DomainGoal::Normalize(_) => panic!(),
}
clauses
}
};

let environment = self.infcx.tcx.lift_to_global(environment)
.expect("environment is not global");
clauses.extend(
self.infcx.tcx.program_clauses_for_env(environment)
.into_iter()
.cloned()
);
clauses
}

fn instantiate_binders_universally(
Expand Down
Loading