diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 0f4a5d16e1759..89bae409a2f4f 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -166,8 +166,8 @@ impl<T> TypedArena<T> {
     where
         T: Copy,
     {
-        assert!(mem::size_of::<T>() != 0);
-        assert!(slice.len() != 0);
+        debug_assert!(mem::size_of::<T>() != 0);
+        debug_assert!(slice.len() != 0);
 
         let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize;
         let at_least_bytes = slice.len() * mem::size_of::<T>();
@@ -318,7 +318,7 @@ impl DroplessArena {
     fn align(&self, align: usize) {
         let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
         self.ptr.set(final_address as *mut u8);
-        assert!(self.ptr <= self.end);
+        debug_assert!(self.ptr <= self.end);
     }
 
     #[inline(never)]
@@ -357,7 +357,7 @@ impl DroplessArena {
     #[inline]
     pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
         unsafe {
-            assert!(bytes != 0);
+            debug_assert!(bytes != 0);
 
             self.align(align);
 
@@ -377,7 +377,7 @@ impl DroplessArena {
 
     #[inline]
     pub fn alloc<T>(&self, object: T) -> &mut T {
-        assert!(!mem::needs_drop::<T>());
+        debug_assert!(!mem::needs_drop::<T>());
 
         let mem = self.alloc_raw(
             mem::size_of::<T>(),
@@ -402,9 +402,9 @@ impl DroplessArena {
     where
         T: Copy,
     {
-        assert!(!mem::needs_drop::<T>());
-        assert!(mem::size_of::<T>() != 0);
-        assert!(slice.len() != 0);
+        debug_assert!(!mem::needs_drop::<T>());
+        debug_assert!(mem::size_of::<T>() != 0);
+        debug_assert!(slice.len() != 0);
 
         let mem = self.alloc_raw(
             slice.len() * mem::size_of::<T>(),
diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs
index 87efc23abc81d..d22e6837782bd 100644
--- a/src/libpanic_unwind/emcc.rs
+++ b/src/libpanic_unwind/emcc.rs
@@ -30,7 +30,7 @@ pub fn payload() -> *mut u8 {
 }
 
 pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
-    assert!(!ptr.is_null());
+    debug_assert!(!ptr.is_null());
     let ex = ptr::read(ptr as *mut _);
     __cxa_free_exception(ptr as *mut _);
     ex
diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs
index 9241240caf043..b1c3d341a889d 100644
--- a/src/librustc/cfg/graphviz.rs
+++ b/src/librustc/cfg/graphviz.rs
@@ -32,7 +32,7 @@ pub struct LabelledCFG<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> LabelledCFG<'a, 'tcx> {
     fn local_id_to_string(&self, local_id: hir::ItemLocalId) -> String {
-        assert!(self.cfg.owner_def_id.is_local());
+        debug_assert!(self.cfg.owner_def_id.is_local());
         let node_id = self.tcx.hir.hir_to_node_id(hir::HirId {
             owner: self.tcx.hir.def_index_to_hir_id(self.cfg.owner_def_id.index).owner,
             local_id
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 14a818ddafb71..136a72acebffa 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -301,7 +301,7 @@ macro_rules! define_dep_nodes {
             pub fn from_def_path_hash(kind: DepKind,
                                       def_path_hash: DefPathHash)
                                       -> DepNode {
-                assert!(kind.can_reconstruct_query_key() && kind.has_params());
+                debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
                 DepNode {
                     kind,
                     hash: def_path_hash.0,
@@ -313,7 +313,7 @@ macro_rules! define_dep_nodes {
             /// does not require any parameters.
             #[inline]
             pub fn new_no_params(kind: DepKind) -> DepNode {
-                assert!(!kind.has_params());
+                debug_assert!(!kind.has_params());
                 DepNode {
                     kind,
                     hash: Fingerprint::ZERO,
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index 7acfe6839540b..1cb42a0c9a787 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -39,7 +39,7 @@ newtype_index!(CrateNum
 
 impl CrateNum {
     pub fn new(x: usize) -> CrateNum {
-        assert!(x < (u32::MAX as usize));
+        debug_assert!(x < (u32::MAX as usize));
         CrateNum(x as u32)
     }
 
@@ -127,7 +127,7 @@ impl DefIndex {
     pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
         let def_index = DefIndex::from_array_index(proc_macro_index,
                                                    DefIndexAddressSpace::High);
-        assert!(def_index != CRATE_DEF_INDEX);
+        debug_assert!(def_index != CRATE_DEF_INDEX);
         def_index
     }
 
@@ -222,7 +222,7 @@ pub struct LocalDefId(DefIndex);
 impl LocalDefId {
     #[inline]
     pub fn from_def_id(def_id: DefId) -> LocalDefId {
-        assert!(def_id.is_local());
+        debug_assert!(def_id.is_local());
         LocalDefId(def_id.index)
     }
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 63755bcea5e62..079e636cc07d0 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -654,8 +654,8 @@ impl<'a> LoweringContext<'a> {
     where
         F: FnOnce(&mut LoweringContext) -> (Vec<hir::GenericParam>, T),
     {
-        assert!(!self.is_collecting_in_band_lifetimes);
-        assert!(self.lifetimes_to_define.is_empty());
+        debug_assert!(!self.is_collecting_in_band_lifetimes);
+        debug_assert!(self.lifetimes_to_define.is_empty());
         let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
 
         self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes;
@@ -735,7 +735,7 @@ impl<'a> LoweringContext<'a> {
     /// When we have either an elided or `'_` lifetime in an impl
     /// header, we convert it to
     fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
-        assert!(self.is_collecting_in_band_lifetimes);
+        debug_assert!(self.is_collecting_in_band_lifetimes);
         let index = self.lifetimes_to_define.len();
         let hir_name = ParamName::Fresh(index);
         self.lifetimes_to_define.push((span, hir_name));
@@ -1596,7 +1596,7 @@ impl<'a> LoweringContext<'a> {
                         if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
                             return n;
                         }
-                        assert!(!def_id.is_local());
+                        debug_assert!(!def_id.is_local());
                         let item_generics =
                             self.cstore.item_generics_cloned_untracked(def_id, self.sess);
                         let n = item_generics.own_counts().lifetimes;
@@ -4369,7 +4369,7 @@ impl<'a> LoweringContext<'a> {
                 has_value: has_value,
             },
             Defaultness::Final => {
-                assert!(has_value);
+                debug_assert!(has_value);
                 hir::Defaultness::Final
             }
         }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index c4b28fe2c4332..d50d0dcc57408 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -257,7 +257,7 @@ impl DefPath {
             debug!("DefPath::make: key={:?}", key);
             match key.disambiguated_data.data {
                 DefPathData::CrateRoot => {
-                    assert!(key.parent.is_none());
+                    debug_assert!(key.parent.is_none());
                     break;
                 }
                 _ => {
@@ -500,7 +500,7 @@ impl Definitions {
         let address_space = super::ITEM_LIKE_SPACE;
         let root_index = self.table.allocate(key, def_path_hash, address_space);
         assert_eq!(root_index, CRATE_DEF_INDEX);
-        assert!(self.def_index_to_node[address_space.index()].is_empty());
+        debug_assert!(self.def_index_to_node[address_space.index()].is_empty());
         self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID);
         self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
 
@@ -522,14 +522,15 @@ impl Definitions {
         debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
                parent, node_id, data);
 
-        assert!(!self.node_to_def_index.contains_key(&node_id),
-                "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
-                node_id,
-                data,
-                self.table.def_key(self.node_to_def_index[&node_id]));
+        debug_assert!(!self.node_to_def_index.contains_key(&node_id),
+                      "adding a def'n for node-id {:?} and data {:?} \
+                       but a previous def'n exists: {:?}",
+                      node_id,
+                      data,
+                      self.table.def_key(self.node_to_def_index[&node_id]));
 
         // The root node must be created with create_root_def()
-        assert!(data != DefPathData::CrateRoot);
+        debug_assert!(data != DefPathData::CrateRoot);
 
         // Find the next free disambiguator for this key.
         let disambiguator = {
@@ -581,8 +582,8 @@ impl Definitions {
     /// AST to HIR lowering.
     pub fn init_node_id_to_hir_id_mapping(&mut self,
                                           mapping: IndexVec<ast::NodeId, hir::HirId>) {
-        assert!(self.node_to_hir_id.is_empty(),
-                "Trying initialize NodeId -> HirId mapping twice");
+        debug_assert!(self.node_to_hir_id.is_empty(),
+                      "Trying initialize NodeId -> HirId mapping twice");
         self.node_to_hir_id = mapping;
     }
 
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index a17c160c4d03e..6d03f09115c21 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -82,7 +82,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
     fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
                                                        node_id: NodeId,
                                                        walk: F) {
-        assert!(self.owner_def_index.is_none());
+        debug_assert!(self.owner_def_index.is_none());
         let owner_def_index = self.hir_map.local_def_id(node_id).index;
         self.owner_def_index = Some(owner_def_index);
         walk(self);
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 49231e58cf0fc..4ef685419d1bd 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -350,7 +350,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn def_key(&self, def_id: DefId) -> DefKey {
-        assert!(def_id.is_local());
+        debug_assert!(def_id.is_local());
         self.definitions.def_key(def_id.index)
     }
 
@@ -361,7 +361,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn def_path(&self, def_id: DefId) -> DefPath {
-        assert!(def_id.is_local());
+        debug_assert!(def_id.is_local());
         self.definitions.def_path(def_id.index)
     }
 
@@ -554,7 +554,7 @@ impl<'hir> Map<'hir> {
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
         let parent = self.get_parent_node(node_id);
-        assert!(self.map[parent.as_usize()].is_body_owner(node_id));
+        debug_assert!(self.map[parent.as_usize()].is_body_owner(node_id));
         parent
     }
 
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 4499a378be21a..802ed4a1abf12 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -2001,7 +2001,7 @@ impl<'a> State<'a> {
         self.popen()?;
         let mut i = 0;
         // Make sure we aren't supplied *both* `arg_names` and `body_id`.
-        assert!(arg_names.is_empty() || body_id.is_none());
+        debug_assert!(arg_names.is_empty() || body_id.is_none());
         self.commasep(Inconsistent, &decl.inputs, |s, ty| {
             s.ibox(indent_unit)?;
             if let Some(arg_name) = arg_names.get(i) {
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs
index 205f8c5ad068c..e2351b66f297c 100644
--- a/src/librustc/infer/anon_types/mod.rs
+++ b/src/librustc/infer/anon_types/mod.rs
@@ -513,7 +513,7 @@ impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> {
     }
 
     fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
-        assert!(!self.map_missing_regions_to_empty);
+        debug_assert!(!self.map_missing_regions_to_empty);
         self.map_missing_regions_to_empty = true;
         let kind = kind.fold_with(self);
         self.map_missing_regions_to_empty = false;
@@ -521,7 +521,7 @@ impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> {
     }
 
     fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
-        assert!(!self.map_missing_regions_to_empty);
+        debug_assert!(!self.map_missing_regions_to_empty);
         kind.fold_with(self)
     }
 }
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index c4de95c60bff5..61e1db07e04d2 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -396,7 +396,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
                 // If `var_values` has become big enough to be heap-allocated,
                 // fill up `indices` to facilitate subsequent lookups.
                 if !var_values.is_array() {
-                    assert!(indices.is_empty());
+                    debug_assert!(indices.is_empty());
                     *indices =
                         var_values.iter()
                             .enumerate()
diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs
index f0b6d25e9dae8..7644a16816886 100644
--- a/src/librustc/infer/canonical/query_result.rs
+++ b/src/librustc/infer/canonical/query_result.rs
@@ -576,8 +576,8 @@ pub fn make_query_outlives<'tcx>(
         givens,
     } = region_constraints;
 
-    assert!(verifys.is_empty());
-    assert!(givens.is_empty());
+    debug_assert!(verifys.is_empty());
+    debug_assert!(givens.is_empty());
 
     let mut outlives: Vec<_> = constraints
             .into_iter()
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index cb4e1ab65e759..13f665218d47e 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -252,7 +252,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                              -> ty::Region<'tcx> {
             // Regions that pre-dated the LUB computation stay as they are.
             if !is_var_in_set(new_vars, r0) {
-                assert!(!r0.is_late_bound());
+                debug_assert!(!r0.is_late_bound());
                 debug!("generalize_region(r0={:?}): not new variable", r0);
                 return r0;
             }
@@ -266,7 +266,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                 debug!("generalize_region(r0={:?}): \
                         non-new-variables found in {:?}",
                        r0, tainted);
-                assert!(!r0.is_late_bound());
+                debug_assert!(!r0.is_late_bound());
                 return r0;
             }
 
@@ -349,7 +349,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                              r0: ty::Region<'tcx>)
                                              -> ty::Region<'tcx> {
             if !is_var_in_set(new_vars, r0) {
-                assert!(!r0.is_late_bound());
+                debug_assert!(!r0.is_late_bound());
                 return r0;
             }
 
@@ -402,7 +402,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                 return rev_lookup(infcx, span, a_map, a_r.unwrap());
             } else if a_r.is_none() && b_r.is_none() {
                 // Not related to bound variables from either fn:
-                assert!(!r0.is_late_bound());
+                debug_assert!(!r0.is_late_bound());
                 return r0;
             } else {
                 // Other:
@@ -468,7 +468,7 @@ fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         // we should only be encountering "escaping" late-bound regions here,
         // because the ones at the current level should have been replaced
         // with fresh variables
-        assert!(match *region {
+        debug_assert!(match *region {
             ty::ReLateBound(..) => false,
             _ => true
         });
@@ -746,13 +746,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     // trait checking, and all of the skolemized regions
                     // appear inside predicates, which always have
                     // binders, so this assert is satisfied.
-                    assert!(current_depth > ty::INNERMOST);
+                    debug_assert!(current_depth > ty::INNERMOST);
 
                     // since leak-check passed, this skolemized region
                     // should only have incoming edges from variables
                     // (which ought not to escape the snapshot, but we
                     // don't check that) or itself
-                    assert!(
+                    debug_assert!(
                         match *r {
                             ty::ReVar(_) => true,
                             ty::ReSkolemized(_, ref br1) => br == br1,
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 0b84c6a0aa77a..8f35d17aa8a01 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1033,7 +1033,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         outlives_env: &OutlivesEnvironment<'tcx>,
         will_later_be_reported_by_nll: bool,
     ) {
-        assert!(self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
+        debug_assert!(self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
                 "region_obligations not empty: {:#?}",
                 self.region_obligations.borrow());
 
@@ -1049,7 +1049,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             lexical_region_resolve::resolve(region_rels, var_infos, data);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
-        assert!(old_value.is_none());
+        debug_assert!(old_value.is_none());
 
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
@@ -1072,9 +1072,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// translate them into the form that the NLL solver
     /// understands. See the NLL module for mode details.
     pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
-        assert!(self.region_obligations.borrow().is_empty(),
-                "region_obligations not empty: {:#?}",
-                self.region_obligations.borrow());
+        debug_assert!(self.region_obligations.borrow().is_empty(),
+                      "region_obligations not empty: {:#?}",
+                      self.region_obligations.borrow());
 
         self.borrow_region_constraints().take_and_reset_data()
     }
@@ -1099,7 +1099,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                          .take()
                                                          .expect("regions already resolved")
                                                          .into_infos_and_data();
-        assert!(data.is_empty());
+        debug_assert!(data.is_empty());
         var_infos
     }
 
diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs
index 6163ec1642001..d60bdb6592c99 100644
--- a/src/librustc/infer/outlives/free_region_map.rs
+++ b/src/librustc/infer/outlives/free_region_map.rs
@@ -48,8 +48,8 @@ impl<'tcx> FreeRegionMap<'tcx> {
                                       r_b: Region<'tcx>)
                                       -> Region<'tcx> {
         debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
-        assert!(is_free(r_a));
-        assert!(is_free(r_b));
+        debug_assert!(is_free(r_a));
+        debug_assert!(is_free(r_b));
         let result = if r_a == r_b { r_a } else {
             match self.relation.postdom_upper_bound(&r_a, &r_b) {
                 None => tcx.mk_region(ty::ReStatic),
@@ -75,7 +75,7 @@ impl<'tcx> FreeRegionRelations<'tcx> for FreeRegionMap<'tcx> {
                         r_a: Region<'tcx>,
                         r_b: Region<'tcx>)
                         -> bool {
-        assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
+        debug_assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
         if let ty::ReStatic = r_b {
             true // `'a <= 'static` is just always true, and not stored in the relation explicitly
         } else {
diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs
index c74783f5e4db5..61316633c822d 100644
--- a/src/librustc/infer/outlives/obligations.rs
+++ b/src/librustc/infer/outlives/obligations.rs
@@ -143,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         body_id: ast::NodeId,
     ) {
-        assert!(
+        debug_assert!(
             !self.in_snapshot.get(),
             "cannot process registered region obligations in a snapshot"
         );
@@ -284,7 +284,7 @@ where
             ty, region, origin
         );
 
-        assert!(!ty.has_escaping_regions());
+        debug_assert!(!ty.has_escaping_regions());
 
         let components = self.tcx.outlives_components(ty);
         self.components_must_outlive(origin, components, region);
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 296808cea2bd7..c0f9b3b1cc1b7 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -301,7 +301,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     ///
     /// Not legal during a snapshot.
     pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
-        assert!(!self.in_snapshot());
+        debug_assert!(!self.in_snapshot());
         (self.var_infos, self.data)
     }
 
@@ -318,7 +318,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     ///
     /// Not legal during a snapshot.
     pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
-        assert!(!self.in_snapshot());
+        debug_assert!(!self.in_snapshot());
 
         // If you add a new field to `RegionConstraintCollector`, you
         // should think carefully about whether it needs to be cleared
@@ -374,8 +374,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
 
     pub fn commit(&mut self, snapshot: RegionSnapshot) {
         debug!("RegionConstraintCollector: commit({})", snapshot.length);
-        assert!(self.undo_log.len() > snapshot.length);
-        assert!(self.undo_log[snapshot.length] == OpenSnapshot);
+        debug_assert!(self.undo_log.len() > snapshot.length);
+        debug_assert!(self.undo_log[snapshot.length] == OpenSnapshot);
 
         if snapshot.length == 0 {
             self.undo_log.truncate(0);
@@ -387,14 +387,14 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
 
     pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
         debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
-        assert!(self.undo_log.len() > snapshot.length);
-        assert!(self.undo_log[snapshot.length] == OpenSnapshot);
+        debug_assert!(self.undo_log.len() > snapshot.length);
+        debug_assert!(self.undo_log[snapshot.length] == OpenSnapshot);
         while self.undo_log.len() > snapshot.length + 1 {
             let undo_entry = self.undo_log.pop().unwrap();
             self.rollback_undo_entry(undo_entry);
         }
         let c = self.undo_log.pop().unwrap();
-        assert!(c == OpenSnapshot);
+        debug_assert!(c == OpenSnapshot);
         self.unification_table.rollback_to(snapshot.region_snapshot);
         self.any_unifications = snapshot.any_unifications;
     }
@@ -474,9 +474,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     ) {
         debug!("pop_skolemized_regions(skols={:?})", skols);
 
-        assert!(self.in_snapshot());
-        assert!(self.undo_log[snapshot.length] == OpenSnapshot);
-        assert!(
+        debug_assert!(self.in_snapshot());
+        debug_assert!(self.undo_log[snapshot.length] == OpenSnapshot);
+        debug_assert!(
             skolemization_count.as_usize() >= skols.len(),
             "popping more skolemized variables than actually exist, \
              sc now = {:?}, skols.len = {:?}",
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index 58eae5e6a5b94..85ebe3b20ece1 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -84,8 +84,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
                 // Shouldn't have any LBR here, so we can safely put
                 // this under a binder below without fear of accidental
                 // capture.
-                assert!(!a.has_escaping_regions());
-                assert!(!b.has_escaping_regions());
+                debug_assert!(!a.has_escaping_regions());
+                debug_assert!(!b.has_escaping_regions());
 
                 // can't make progress on `A <: B` if both A and B are
                 // type variables, so record an obligation. We also
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index b949fd02126ba..57aca18368245 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -104,7 +104,7 @@ fn get_cfg_indices<'a>(id: hir::ItemLocalId,
 
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
     fn has_bitset_for_local_id(&self, n: hir::ItemLocalId) -> bool {
-        assert!(n != hir::DUMMY_ITEM_LOCAL_ID);
+        debug_assert!(n != hir::DUMMY_ITEM_LOCAL_ID);
         self.local_id_to_index.contains_key(&n)
     }
 }
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 4c99b46ddff6e..326ce9ed1d9c2 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -210,7 +210,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if src.dylib.is_none() &&
            !formats.contains_key(&cnum) &&
            tcx.dep_kind(cnum) == DepKind::Explicit {
-            assert!(src.rlib.is_some() || src.rmeta.is_some());
+            debug_assert!(src.rlib.is_some() || src.rmeta.is_some());
             info!("adding staticlib: {}", tcx.crate_name(cnum));
             add_library(tcx, cnum, RequireStatic, &mut formats);
             ret[cnum.as_usize() - 1] = Linkage::Static;
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index b828b1bd30a94..f706d8b565e61 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -662,7 +662,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn live_on_entry(&self, ln: LiveNode, var: Variable)
                       -> Option<LiveNodeKind> {
-        assert!(ln.is_valid());
+        debug_assert!(ln.is_valid());
         let reader = self.users[self.idx(ln, var)].reader;
         if reader.is_valid() {Some(self.ir.lnk(reader))} else {None}
     }
@@ -677,13 +677,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
-        assert!(ln.is_valid());
+        debug_assert!(ln.is_valid());
         self.users[self.idx(ln, var)].used
     }
 
     fn assigned_on_entry(&self, ln: LiveNode, var: Variable)
                          -> Option<LiveNodeKind> {
-        assert!(ln.is_valid());
+        debug_assert!(ln.is_valid());
         let writer = self.users[self.idx(ln, var)].writer;
         if writer.is_valid() {Some(self.ir.lnk(writer))} else {None}
     }
@@ -1356,7 +1356,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                     self.propagate_through_expr(&cond, ln)
                 }
             };
-            assert!(cond_ln == new_cond_ln);
+            debug_assert!(cond_ln == new_cond_ln);
             assert!(body_ln == self.propagate_through_block(body, cond_ln));
         }
 
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index ebdc9c922b1df..4648378625711 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -506,7 +506,7 @@ impl<'tcx> ScopeTree {
 
         if let Some(p) = parent {
             let prev = self.parent_map.insert(child, p);
-            assert!(prev.is_none());
+            debug_assert!(prev.is_none());
         }
 
         // record the destruction scopes for later so we can query them
@@ -539,21 +539,21 @@ impl<'tcx> ScopeTree {
                              sup_closure: hir::ItemLocalId) {
         debug!("record_closure_parent(sub_closure={:?}, sup_closure={:?})",
                sub_closure, sup_closure);
-        assert!(sub_closure != sup_closure);
+        debug_assert!(sub_closure != sup_closure);
         let previous = self.closure_tree.insert(sub_closure, sup_closure);
-        assert!(previous.is_none());
+        debug_assert!(previous.is_none());
     }
 
     fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
         debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
-        assert!(var != lifetime.item_local_id());
+        debug_assert!(var != lifetime.item_local_id());
         self.var_map.insert(var, lifetime);
     }
 
     fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option<Scope>) {
         debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
         if let Some(lifetime) = lifetime {
-            assert!(var != lifetime.item_local_id());
+            debug_assert!(var != lifetime.item_local_id());
         }
         self.rvalue_scopes.insert(var, lifetime);
     }
@@ -700,7 +700,7 @@ impl<'tcx> ScopeTree {
             // Both scopes are at the same depth, and we know they're not equal
             // because that case was tested for at the top of this function. So
             // we can trivially move them both up one level now.
-            assert!(parent_a_depth != 0);
+            debug_assert!(parent_a_depth != 0);
             a = parent_a;
             b = parent_b;
         }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index ca8fe463119c1..055edd4511dc2 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -651,7 +651,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
                     };
 
-                    assert!(exist_ty_did.is_local());
+                    debug_assert!(exist_ty_did.is_local());
                     // Resolve the lifetimes that are applied to the existential type.
                     // These are resolved in the current scope.
                     // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
@@ -810,7 +810,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }
             Const(_, _) => {
                 // Only methods and types support generics.
-                assert!(trait_item.generics.params.is_empty());
+                debug_assert!(trait_item.generics.params.is_empty());
                 intravisit::walk_trait_item(self, trait_item);
             }
         }
@@ -885,7 +885,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }
             Const(_, _) => {
                 // Only methods and types support generics.
-                assert!(impl_item.generics.params.is_empty());
+                debug_assert!(impl_item.generics.params.is_empty());
                 intravisit::walk_impl_item(self, impl_item);
             }
         }
@@ -2589,7 +2589,7 @@ fn insert_late_bound_lifetimes(
                param.id);
 
         let inserted = map.late_bound.insert(param.id);
-        assert!(inserted, "visited lifetime {:?} twice", param.id);
+        debug_assert!(inserted, "visited lifetime {:?} twice", param.id);
     }
 
     return;
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 4164fe3fd933b..39d105970b097 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -347,7 +347,7 @@ impl<'s> AllocDecodingSession<'s> {
                     Ok(alloc_id)
                 },
                 AllocKind::Fn => {
-                    assert!(alloc_id.is_none());
+                    debug_assert!(alloc_id.is_none());
                     trace!("creating fn alloc id");
                     let instance = ty::Instance::decode(decoder)?;
                     trace!("decoded fn alloc instance: {:?}", instance);
@@ -355,7 +355,7 @@ impl<'s> AllocDecodingSession<'s> {
                     Ok(alloc_id)
                 },
                 AllocKind::Static => {
-                    assert!(alloc_id.is_none());
+                    debug_assert!(alloc_id.is_none());
                     trace!("creating extern static alloc id at");
                     let did = DefId::decode(decoder)?;
                     let alloc_id = decoder.tcx().alloc_map.lock().intern_static(did);
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 4bfb4c96497ff..bdcb261fbecb5 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -147,7 +147,7 @@ impl<'tcx> Mir<'tcx> {
         span: Span,
     ) -> Self {
         // We need `arg_count` locals, and one for the return place
-        assert!(
+        debug_assert!(
             local_decls.len() >= arg_count + 1,
             "expected at least {} locals, got {}",
             arg_count + 1,
@@ -306,7 +306,7 @@ impl<'tcx> Mir<'tcx> {
         if idx < stmts.len() {
             &stmts[idx].source_info
         } else {
-            assert!(idx == stmts.len());
+            debug_assert!(idx == stmts.len());
             &block.terminator().source_info
         }
     }
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index f0d6b8170eb64..c11e5c9c62682 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -165,7 +165,7 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 
     pub fn modify_size_estimate(&mut self, delta: usize) {
-        assert!(self.size_estimate.is_some());
+        debug_assert!(self.size_estimate.is_some());
         if let Some(size_estimate) = self.size_estimate {
             self.size_estimate = Some(size_estimate + delta);
         }
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index b55843ac527df..2383277df7806 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -83,8 +83,8 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
             ProjectionElem::Downcast(adt_def1, index) =>
                 match self.to_ty(tcx).sty {
                     ty::TyAdt(adt_def, substs) => {
-                        assert!(adt_def.is_enum());
-                        assert!(index < adt_def.variants.len());
+                        debug_assert!(adt_def.is_enum());
+                        debug_assert!(index < adt_def.variants.len());
                         assert_eq!(adt_def, adt_def1);
                         PlaceTy::Downcast { adt_def,
                                              substs,
diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs
index 1eee6508c59cc..64b19af2241a4 100644
--- a/src/librustc/session/code_stats.rs
+++ b/src/librustc/session/code_stats.rs
@@ -142,7 +142,7 @@ impl CodeStats {
                              indent, name, size - discr_size);
                     "        "
                 } else {
-                    assert!(i < 1);
+                    debug_assert!(i < 1);
                     "    "
                 };
                 max_variant_size = cmp::max(max_variant_size, size);
@@ -182,9 +182,9 @@ impl CodeStats {
                 }
             }
 
-            assert!(max_variant_size <= info.overall_size,
-                    "max_variant_size {} !<= {} overall_size",
-                    max_variant_size, info.overall_size);
+            debug_assert!(max_variant_size <= info.overall_size,
+                          "max_variant_size {} !<= {} overall_size",
+                          max_variant_size, info.overall_size);
             if max_variant_size < info.overall_size {
                 println!("print-type-size {}end padding: {} bytes",
                          indent, info.overall_size - max_variant_size);
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 7b8bbbf4a10e0..923eb919146bf 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -848,7 +848,7 @@ impl Session {
         let mut ret = true;
         match self.optimization_fuel_crate {
             Some(ref c) if c == crate_name => {
-                assert!(self.query_threads() == 1);
+                debug_assert!(self.query_threads() == 1);
                 let fuel = self.optimization_fuel_limit.get();
                 ret = fuel != 0;
                 if fuel == 0 && !self.out_of_fuel.get() {
@@ -862,7 +862,7 @@ impl Session {
         }
         match self.print_fuel_crate {
             Some(ref c) if c == crate_name => {
-                assert!(self.query_threads() == 1);
+                debug_assert!(self.query_threads() == 1);
                 self.print_fuel.set(self.print_fuel.get() + 1);
             }
             _ => {}
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c04785aac2095..d5c3c9e882c81 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -504,7 +504,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// going to help).
     pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
         let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned());
-        assert!(cycle.len() > 0);
+        debug_assert!(cycle.len() > 0);
 
         debug!("report_overflow_error_cycle: cycle={:?}", cycle);
 
@@ -1182,7 +1182,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                                    type_def_id: DefId)
                                                    -> DiagnosticBuilder<'tcx>
     {
-        assert!(type_def_id.is_local());
+        debug_assert!(type_def_id.is_local());
         let span = self.hir.span_if_local(type_def_id).unwrap();
         let span = self.sess.codemap().def_span(span);
         let mut err = struct_span_err!(self.sess, span, E0072,
@@ -1304,7 +1304,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 } else {
                     let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
                     // both must be type variables, or the other would've been instantiated
-                    assert!(a.is_ty_var() && b.is_ty_var());
+                    debug_assert!(a.is_ty_var() && b.is_ty_var());
                     self.need_type_info_err(body_id,
                                             obligation.cause.span,
                                             a).emit();
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index b7d3ad76588f7..688e35f55952c 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -146,7 +146,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         debug!("normalize_projection_type(projection_ty={:?})",
                projection_ty);
 
-        assert!(!projection_ty.has_escaping_regions());
+        debug_assert!(!projection_ty.has_escaping_regions());
 
         // FIXME(#20304) -- cache
 
@@ -197,7 +197,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
 
         debug!("register_predicate_obligation(obligation={:?})", obligation);
 
-        assert!(!infcx.is_in_snapshot());
+        debug_assert!(!infcx.is_in_snapshot());
 
         self.predicates.register_obligation(PendingPredicateObligation {
             obligation,
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 1ce60d8f05599..a12595e89460b 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1142,7 +1142,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 if !is_default {
                     true
                 } else if obligation.param_env.reveal == Reveal::All {
-                    assert!(!poly_trait_ref.needs_infer());
+                    debug_assert!(!poly_trait_ref.needs_infer());
                     if !poly_trait_ref.needs_subst() {
                         true
                     } else {
@@ -1697,7 +1697,7 @@ impl<'tcx> ProjectionCache<'tcx> {
         debug!("ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
                key, value);
         let fresh_key = self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value));
-        assert!(!fresh_key, "never started projecting `{:?}`", key);
+        debug_assert!(!fresh_key, "never started projecting `{:?}`", key);
     }
 
     /// Mark the relevant projection cache key as having its derived obligations
@@ -1749,13 +1749,13 @@ impl<'tcx> ProjectionCache<'tcx> {
     /// be different).
     fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous);
-        assert!(!fresh, "never started projecting `{:?}`", key);
+        debug_assert!(!fresh, "never started projecting `{:?}`", key);
     }
 
     /// Indicates that trying to normalize `key` resulted in
     /// error.
     fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Error);
-        assert!(!fresh, "never started projecting `{:?}`", key);
+        debug_assert!(!fresh, "never started projecting `{:?}`", key);
     }
 }
diff --git a/src/librustc/traits/query/normalize_erasing_regions.rs b/src/librustc/traits/query/normalize_erasing_regions.rs
index 1cb96a3e33f43..711449ad09192 100644
--- a/src/librustc/traits/query/normalize_erasing_regions.rs
+++ b/src/librustc/traits/query/normalize_erasing_regions.rs
@@ -66,7 +66,7 @@ impl<'cx, 'tcx> TyCtxt<'cx, 'tcx, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        assert!(!value.needs_subst());
+        debug_assert!(!value.needs_subst());
         let value = self.erase_late_bound_regions(value);
         self.normalize_erasing_regions(param_env, value)
     }
diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs
index f79ce73ad928a..191d0c6733bc7 100644
--- a/src/librustc/traits/query/outlives_bounds.rs
+++ b/src/librustc/traits/query/outlives_bounds.rs
@@ -117,7 +117,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
                 return vec![];
             }
         };
-        assert!(result.value.is_proven());
+        debug_assert!(result.value.is_proven());
 
         let result = self.instantiate_query_result_and_region_obligations(
             &ObligationCause::misc(span, body_id), param_env, &orig_values, &result);
diff --git a/src/librustc/traits/query/type_op/custom.rs b/src/librustc/traits/query/type_op/custom.rs
index cc752d21ab2b8..033babd3eee59 100644
--- a/src/librustc/traits/query/type_op/custom.rs
+++ b/src/librustc/traits/query/type_op/custom.rs
@@ -82,7 +82,7 @@ fn scrape_region_constraints<'gcx, 'tcx, R>(
     // obligations that resulted). So this vector should be empty on
     // entry.
     let pre_obligations = infcx.take_registered_region_obligations();
-    assert!(
+    debug_assert!(
         pre_obligations.is_empty(),
         "scrape_region_constraints: incoming region obligations = {:#?}",
         pre_obligations,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 40171345f558b..cdf58cd1256a4 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -492,8 +492,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     /// false overflow results (#47139) and because it costs
     /// computation time.
     pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
-        assert!(self.intercrate.is_some());
-        assert!(self.intercrate_ambiguity_causes.is_none());
+        debug_assert!(self.intercrate.is_some());
+        debug_assert!(self.intercrate_ambiguity_causes.is_none());
         self.intercrate_ambiguity_causes = Some(vec![]);
         debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
     }
@@ -502,7 +502,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     /// was enabled and disables tracking at the same time. If
     /// tracking is not enabled, just returns an empty vector.
     pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
-        assert!(self.intercrate.is_some());
+        debug_assert!(self.intercrate.is_some());
         self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
     }
 
@@ -563,7 +563,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
                   -> SelectionResult<'tcx, Selection<'tcx>> {
         debug!("select({:?})", obligation);
-        assert!(!obligation.predicate.has_escaping_regions());
+        debug_assert!(!obligation.predicate.has_escaping_regions());
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
 
@@ -571,7 +571,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             Err(SelectionError::Overflow) => {
                 // In standard mode, overflow must have been caught and reported
                 // earlier.
-                assert!(self.query_mode == TraitQueryMode::Canonical);
+                debug_assert!(self.query_mode == TraitQueryMode::Canonical);
                 return Err(SelectionError::Overflow);
             },
             Err(e) => { return Err(e); },
@@ -581,7 +581,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         match self.confirm_candidate(obligation, candidate) {
             Err(SelectionError::Overflow) => {
-                assert!(self.query_mode == TraitQueryMode::Canonical);
+                debug_assert!(self.query_mode == TraitQueryMode::Canonical);
                 return Err(SelectionError::Overflow);
             },
             Err(e) => Err(e),
@@ -609,7 +609,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         // This fatal query is a stopgap that should only be used in standard mode,
         // where we do not expect overflow to be propagated.
-        assert!(self.query_mode == TraitQueryMode::Standard);
+        debug_assert!(self.query_mode == TraitQueryMode::Standard);
 
         self.evaluate_obligation_recursively(obligation)
             .expect("Overflow should be caught earlier in standard query mode")
@@ -662,7 +662,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
-                assert!(!t.has_escaping_regions());
+                debug_assert!(!t.has_escaping_regions());
                 let obligation = obligation.with(t.clone());
                 self.evaluate_trait_predicate_recursively(previous_stack, obligation)
             }
@@ -1076,7 +1076,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         debug!("candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
                cache_fresh_trait_pred,
                stack);
-        assert!(!stack.obligation.predicate.has_escaping_regions());
+        debug_assert!(!stack.obligation.predicate.has_escaping_regions());
 
         if let Some(c) = self.check_candidate_cache(stack.obligation.param_env,
                                                     &cache_fresh_trait_pred) {
@@ -1572,7 +1572,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
                 self.infcx.pop_skolemized(skol_map, snapshot);
 
-                assert!(result);
+                debug_assert!(result);
                 true
             }
         }
@@ -1586,7 +1586,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
                         -> bool
     {
-        assert!(!skol_trait_ref.has_escaping_regions());
+        debug_assert!(!skol_trait_ref.has_escaping_regions());
         if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env)
                                   .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) {
             return false;
@@ -2500,7 +2500,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             let result =
                 this.match_projection_obligation_against_definition_bounds(obligation,
                                                                            snapshot);
-            assert!(result);
+            debug_assert!(result);
         })
     }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 06f9b446146e5..51ee20dcb4706 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -123,7 +123,7 @@ pub fn find_associated_item<'a, 'tcx>(
     substs: &'tcx Substs<'tcx>,
     impl_data: &super::VtableImplData<'tcx, ()>,
 ) -> (DefId, &'tcx Substs<'tcx>) {
-    assert!(!substs.needs_infer());
+    debug_assert!(!substs.needs_infer());
 
     let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
     let trait_def = tcx.trait_def(trait_def_id);
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index f9c0581d3ca37..cffe3f1d48b06 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -250,7 +250,7 @@ impl<'a, 'gcx, 'tcx> Graph {
                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
                   impl_def_id: DefId)
                   -> Result<Option<OverlapError>, OverlapError> {
-        assert!(impl_def_id.is_local());
+        debug_assert!(impl_def_id.is_local());
 
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
         let trait_def_id = trait_ref.def_id;
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index 967a3324cfb2a..a1171eaf37d79 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -156,7 +156,7 @@ pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
     // Handle shorthands first, if we have an usize > 0x80.
     if decoder.positioned_at_shorthand() {
         let pos = decoder.read_usize()?;
-        assert!(pos >= SHORTHAND_OFFSET);
+        debug_assert!(pos >= SHORTHAND_OFFSET);
         let shorthand = pos - SHORTHAND_OFFSET;
 
         decoder.cached_ty_for_shorthand(shorthand, |decoder| {
@@ -180,7 +180,7 @@ pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
                 // Handle shorthands first, if we have an usize > 0x80.
                 if decoder.positioned_at_shorthand() {
                     let pos = decoder.read_usize()?;
-                    assert!(pos >= SHORTHAND_OFFSET);
+                    debug_assert!(pos >= SHORTHAND_OFFSET);
                     let shorthand = pos - SHORTHAND_OFFSET;
 
                     decoder.with_position(shorthand, ty::Predicate::decode)
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 98568f860a4fd..80156b617689b 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -803,9 +803,9 @@ impl<'tcx> CommonTypes<'tcx> {
     fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
         // Ensure our type representation does not grow
         #[cfg(target_pointer_width = "64")]
-        assert!(mem::size_of::<ty::TypeVariants>() <= 24);
+        debug_assert!(mem::size_of::<ty::TypeVariants>() <= 24);
         #[cfg(target_pointer_width = "64")]
-        assert!(mem::size_of::<ty::TyS>() <= 32);
+        debug_assert!(mem::size_of::<ty::TyS>() <= 32);
 
         let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
         let mk_region = |r| {
@@ -1921,7 +1921,7 @@ pub mod tls {
         where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
     {
         let gcx = GCX_PTR.with(|lock| *lock.lock());
-        assert!(gcx != 0);
+        debug_assert!(gcx != 0);
         let gcx = &*(gcx as *const GlobalCtxt<'_>);
         let tcx = TyCtxt {
             gcx,
@@ -1971,7 +1971,7 @@ pub mod tls {
         with_context(|context| {
             unsafe {
                 let gcx = tcx.gcx as *const _ as usize;
-                assert!(context.tcx.gcx as *const _ as usize == gcx);
+                debug_assert!(context.tcx.gcx as *const _ as usize == gcx);
                 let context: &ImplicitCtxt = mem::transmute(context);
                 f(context)
             }
@@ -1990,8 +1990,8 @@ pub mod tls {
             unsafe {
                 let gcx = tcx.gcx as *const _ as usize;
                 let interners = tcx.interners as *const _ as usize;
-                assert!(context.tcx.gcx as *const _ as usize == gcx);
-                assert!(context.tcx.interners as *const _ as usize == interners);
+                debug_assert!(context.tcx.gcx as *const _ as usize == gcx);
+                debug_assert!(context.tcx.interners as *const _ as usize == interners);
                 let context: &ImplicitCtxt = mem::transmute(context);
                 f(context)
             }
@@ -2407,7 +2407,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     if param.index == 0 {
                         ty.into()
                     } else {
-                        assert!(has_default);
+                        debug_assert!(has_default);
                         self.type_of(param.def_id).subst(self, substs).into()
                     }
                 }
@@ -2561,8 +2561,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
         -> &'tcx Slice<ExistentialPredicate<'tcx>> {
-        assert!(!eps.is_empty());
-        assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) != Ordering::Greater));
+        debug_assert!(!eps.is_empty());
+        debug_assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) != Ordering::Greater));
         self._intern_existential_predicates(eps)
     }
 
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index e4484041b065c..2923b8aa7f169 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -482,7 +482,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     // binders in `bound2_value` (nmatsakis added in
                     // the course of this PR; seems like a reasonable
                     // sanity check though).
-                    assert!(debruijn == current_depth);
+                    debug_assert!(debruijn == current_depth);
                     self.mk_region(ty::ReLateBound(current_depth, br))
                 }
                 _ => {
@@ -518,7 +518,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         let mut collector = LateBoundRegionsCollector::new(just_constraint);
         let result = value.skip_binder().visit_with(&mut collector);
-        assert!(!result); // should never have stopped early
+        debug_assert!(!result); // should never have stopped early
         collector.regions
     }
 
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 66edbeff749f7..2d28a93b88214 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -143,9 +143,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
 impl<'a, 'b, 'tcx> Instance<'tcx> {
     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
                -> Instance<'tcx> {
-        assert!(!substs.has_escaping_regions(),
-                "substs of instance {:?} not normalized for codegen: {:?}",
-                def_id, substs);
+        debug_assert!(!substs.has_escaping_regions(),
+                      "substs of instance {:?} not normalized for codegen: {:?}",
+                      def_id, substs);
         Instance { def: InstanceDef::Item(def_id), substs: substs }
     }
 
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index c44b7327a0830..61126f8804b6c 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -196,7 +196,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let key = self.def_key(def_id);
         match key.disambiguated_data.data {
             DefPathData::CrateRoot => {
-                assert!(key.parent.is_none());
+                debug_assert!(key.parent.is_none());
                 self.push_krate_path(buffer, def_id.krate);
             }
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 81cc897232ab0..aafebb9c3248b 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -215,7 +215,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
         let dl = self.data_layout();
         let scalar_unit = |value: Primitive| {
             let bits = value.size(dl).bits();
-            assert!(bits <= 128);
+            debug_assert!(bits <= 128);
             Scalar {
                 value,
                 valid_range: 0..=(!0 >> (128 - bits))
@@ -466,7 +466,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
         let univariant = |fields: &[TyLayout], repr: &ReprOptions, kind| {
             Ok(tcx.intern_layout(univariant_uninterned(fields, repr, kind)?))
         };
-        assert!(!ty.has_infer_types());
+        debug_assert!(!ty.has_infer_types());
 
         Ok(match ty.sty {
             // Basic scalars.
@@ -634,7 +634,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             ty::TyAdt(def, ..) if def.repr.simd() => {
                 let element = self.layout_of(ty.simd_type(tcx))?;
                 let count = ty.simd_size(tcx) as u64;
-                assert!(count > 0);
+                debug_assert!(count > 0);
                 let scalar = match element.abi {
                     Abi::Scalar(ref scalar) => scalar.clone(),
                     _ => {
@@ -697,7 +697,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
                     let mut size = Size::ZERO;
                     for field in &variants[0] {
-                        assert!(!field.is_unsized());
+                        debug_assert!(!field.is_unsized());
 
                         if packed {
                             let field_pack = field.align.min(pack);
@@ -903,7 +903,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     min = 0;
                     max = 0;
                 }
-                assert!(min <= max, "discriminant range is {}...{}", min, max);
+                debug_assert!(min <= max, "discriminant range is {}...{}", min, max);
                 let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
 
                 let mut align = dl.aggregate_align;
@@ -1283,7 +1283,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    param_env: ty::ParamEnv<'tcx>)
                    -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
-        assert!(!ty.has_infer_types());
+        debug_assert!(!ty.has_infer_types());
 
         // First try computing a static layout.
         let err = match tcx.layout_of(param_env.and(ty)) {
@@ -1300,7 +1300,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
                 let tail = tcx.struct_tail(pointee);
                 match tail.sty {
                     ty::TyParam(_) | ty::TyProjection(_) => {
-                        assert!(tail.has_param_types() || tail.has_self_ty());
+                        debug_assert!(tail.has_param_types() || tail.has_self_ty());
                         Ok(SizeSkeleton::Pointer {
                             non_zero,
                             tail: tcx.erase_regions(&tail)
@@ -1599,7 +1599,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
             // Potentially-fat pointers.
             ty::TyRef(_, pointee, _) |
             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
-                assert!(i < this.fields.count());
+                debug_assert!(i < this.fields.count());
 
                 // Reuse the fat *T type as its own thin pointer data field.
                 // This provides information about e.g. DST struct pointees
@@ -1711,7 +1711,7 @@ impl Niche {
         }
         let Scalar { value, valid_range: ref v } = self.scalar;
         let bits = value.size(cx).bits();
-        assert!(bits <= 128);
+        debug_assert!(bits <= 128);
         let max_value = !0u128 >> (128 - bits);
         let start = v.end().wrapping_add(1) & max_value;
         let end = v.end().wrapping_add(count) & max_value;
@@ -1728,7 +1728,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             let Scalar { value, valid_range: ref v } = *scalar;
 
             let bits = value.size(self).bits();
-            assert!(bits <= 128);
+            debug_assert!(bits <= 128);
             let max_value = !0u128 >> (128 - bits);
 
             // Find out how many values are outside the valid range.
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 4fda3bdca3dfc..0ddc233d91a0c 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -616,9 +616,9 @@ unsafe impl<T: Sync> Sync for Slice<T> {}
 impl<T: Copy> Slice<T> {
     #[inline]
     fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx Slice<T> {
-        assert!(!mem::needs_drop::<T>());
-        assert!(mem::size_of::<T>() != 0);
-        assert!(slice.len() != 0);
+        debug_assert!(!mem::needs_drop::<T>());
+        debug_assert!(mem::size_of::<T>() != 0);
+        debug_assert!(slice.len() != 0);
 
         // Align up the size of the len (usize) field
         let align = mem::align_of::<T>();
@@ -716,7 +716,7 @@ impl<T> Slice<T> {
         #[repr(align(64), C)]
         struct EmptySlice([u8; 64]);
         static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]);
-        assert!(mem::align_of::<T>() <= 64);
+        debug_assert!(mem::align_of::<T>() <= 64);
         unsafe {
             &*(&EMPTY_SLICE as *const _ as *const Slice<T>)
         }
@@ -2023,7 +2023,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
 
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(&self) -> &VariantDef {
-        assert!(self.is_struct() || self.is_union());
+        debug_assert!(self.is_struct() || self.is_union());
         &self.variants[0]
     }
 
diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs
index 56a8c13a8d3b8..d02f56113cde2 100644
--- a/src/librustc/ty/query/job.rs
+++ b/src/librustc/ty/query/job.rs
@@ -514,7 +514,7 @@ fn deadlock(tcx: TyCtxt<'_, '_, '_>, registry: &rayon_core::Registry) {
     // which in turn will wait on X causing a deadlock. We have a false dependency from
     // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here
     // only considers the true dependency and won't detect a cycle.
-    assert!(found_cycle);
+    debug_assert!(found_cycle);
 
     // FIXME: Ensure this won't cause a deadlock before we return
     for waiter in wakelist.into_iter() {
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index aa42b4072bd8a..e93870be38404 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -234,7 +234,7 @@ impl<'sess> OnDiskCache<'sess> {
                 // const eval is special, it only encodes successfully evaluated constants
                 use ty::query::QueryAccessors;
                 let cache = const_eval::query_cache(tcx).borrow();
-                assert!(cache.active.is_empty());
+                debug_assert!(cache.active.is_empty());
                 for (key, entry) in cache.results.iter() {
                     use ty::query::config::QueryDescription;
                     if const_eval::cache_on_disk(key.clone()) {
@@ -1100,7 +1100,7 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     time(tcx.sess, desc, || {
 
     let map = Q::query_cache(tcx).borrow();
-    assert!(map.active.is_empty());
+    debug_assert!(map.active.is_empty());
     for (key, entry) in map.results.iter() {
         if Q::cache_on_disk(key.clone()) {
             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 7a9827b50a176..c2f1b2b403158 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -243,7 +243,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub(super) fn report_cycle(self, CycleError { usage, cycle: stack }: CycleError<'gcx>)
         -> DiagnosticBuilder<'a>
     {
-        assert!(!stack.is_empty());
+        debug_assert!(!stack.is_empty());
 
         let fix_span = |span: Span, query: &Query<'gcx>| {
             self.sess.codemap().def_span(query.default_span(self, span))
@@ -476,10 +476,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
             use ich::Fingerprint;
 
-            assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
-                    self.dep_graph.prev_fingerprint_of(dep_node),
-                    "Fingerprint for green query instance not loaded \
-                        from cache: {:?}", dep_node);
+            debug_assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
+                          self.dep_graph.prev_fingerprint_of(dep_node),
+                          "Fingerprint for green query instance not loaded \
+                           from cache: {:?}", dep_node);
 
             debug!("BEGIN verify_ich({:?})", dep_node);
             let mut hcx = self.create_stable_hashing_context();
@@ -492,8 +492,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
             let old_hash = self.dep_graph.fingerprint_of(dep_node_index);
 
-            assert!(new_hash == old_hash, "Found unstable fingerprints \
-                for {:?}", dep_node);
+            debug_assert!(new_hash == old_hash, "Found unstable fingerprints for {:?}", dep_node);
         }
 
         if self.sess.opts.debugging_opts.query_dep_graph {
@@ -516,11 +515,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         //    in DepGraph::try_mark_green()
         // 2. Two distinct query keys get mapped to the same DepNode
         //    (see for example #48923)
-        assert!(!self.dep_graph.dep_node_exists(&dep_node),
-                "Forcing query with already existing DepNode.\n\
-                    - query-key: {:?}\n\
-                    - dep-node: {:?}",
-                key, dep_node);
+        debug_assert!(!self.dep_graph.dep_node_exists(&dep_node),
+                      "Forcing query with already existing DepNode.\n\
+                       - query-key: {:?}\n\
+                       - dep-node: {:?}",
+                      key, dep_node);
 
         profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
         let res = job.start(self, |tcx| {
@@ -565,8 +564,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let dep_node = Q::to_dep_node(self, &key);
 
         // Ensuring an "input" or anonymous query makes no sense
-        assert!(!dep_node.kind.is_anon());
-        assert!(!dep_node.kind.is_input());
+        debug_assert!(!dep_node.kind.is_anon());
+        debug_assert!(!dep_node.kind.is_input());
         if self.try_mark_green_and_read(&dep_node).is_none() {
             // A None return from `try_mark_green_and_read` means that this is either
             // a new dep node or that the dep node has already been marked red.
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 4e8f33d6a4a03..dc1d6d19ad907 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -331,7 +331,7 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
                            -> RelateResult<'tcx, GeneratorWitness<'tcx>>
         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
     {
-        assert!(a.0.len() == b.0.len());
+        debug_assert!(a.0.len() == b.0.len());
         let tcx = relation.tcx();
         let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
         Ok(GeneratorWitness(types))
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index dd38188824338..17ca270bd4a9e 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
     pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
         -> ty::TraitRef<'tcx>  {
         // otherwise the escaping regions would be captured by the binder
-        assert!(!self_ty.has_escaping_regions());
+        debug_assert!(!self_ty.has_escaping_regions());
 
         ty::TraitRef {
             def_id: self.def_id,
@@ -753,7 +753,7 @@ impl<T> Binder<T> {
     pub fn dummy<'tcx>(value: T) -> Binder<T>
         where T: TypeFoldable<'tcx>
     {
-        assert!(!value.has_escaping_regions());
+        debug_assert!(!value.has_escaping_regions());
         Binder(value)
     }
 
@@ -1247,7 +1247,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
                         -> ty::ProjectionPredicate<'tcx>
     {
         // otherwise the escaping regions would be captured by the binders
-        assert!(!self_ty.has_escaping_regions());
+        debug_assert!(!self_ty.has_escaping_regions());
 
         ty::ProjectionPredicate {
             projection_ty: ty::ProjectionTy {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 95caa0c185be1..22f2a6a6ff5f1 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -77,7 +77,7 @@ impl<'tcx> Discr<'tcx> {
             let min = sext(1_u128 << (bit_size - 1));
             let max = i128::max_value() >> shift;
             let val = sext(self.val);
-            assert!(n < (i128::max_value() as u128));
+            debug_assert!(n < (i128::max_value() as u128));
             let n = n as i128;
             let oflo = val > max - n;
             let val = if oflo {
@@ -366,7 +366,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                erased_self_ty,
                predicates);
 
-        assert!(!erased_self_ty.has_escaping_regions());
+        debug_assert!(!erased_self_ty.has_escaping_regions());
 
         traits::elaborate_predicates(self, predicates)
             .filter_map(|predicate| {
@@ -920,7 +920,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     };
 
-    assert!(!ty.needs_infer());
+    debug_assert!(!ty.needs_infer());
 
     match ty.sty {
         // Fast-path for primitive types
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index b99cdd59773aa..eb0f7a1d37078 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -158,7 +158,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
         let infcx = &mut self.infcx;
         let param_env = self.param_env;
         self.out.iter()
-                .inspect(|pred| assert!(!pred.has_escaping_regions()))
+                .inspect(|pred| debug_assert!(!pred.has_escaping_regions()))
                 .flat_map(|pred| {
                     let mut selcx = traits::SelectionContext::new(infcx);
                     let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
@@ -424,7 +424,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                         // Yes, resolved, proceed with the
                         // result. Should never return false because
                         // `ty` is not a TyInfer.
-                        assert!(self.compute(ty));
+                        debug_assert!(self.compute(ty));
                     }
                 }
             }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index bb54e18360495..80c3086ac025f 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -318,7 +318,7 @@ impl PrintContext {
             let mut child_types = 0;
             if let Some(def_id) = generics.parent {
                 // Methods.
-                assert!(is_value_path);
+                debug_assert!(is_value_path);
                 child_types = child_own_counts.types;
                 generics = tcx.generics_of(def_id);
                 own_counts = generics.own_counts();
diff --git a/src/librustc/util/time_graph.rs b/src/librustc/util/time_graph.rs
index a8502682a806b..b7fac004a6d9f 100644
--- a/src/librustc/util/time_graph.rs
+++ b/src/librustc/util/time_graph.rs
@@ -84,7 +84,7 @@ impl TimeGraph {
                 open_work_package: None,
             });
 
-            assert!(data.open_work_package.is_none());
+            debug_assert!(data.open_work_package.is_none());
             data.open_work_package = Some((Instant::now(), work_package_kind, name.to_string()));
         }
 
@@ -121,7 +121,7 @@ impl TimeGraph {
         let table = self.data.lock().unwrap();
 
         for data in table.values() {
-            assert!(data.open_work_package.is_none());
+            debug_assert!(data.open_work_package.is_none());
         }
 
         let mut threads: Vec<PerThread> =
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 49bd69f826216..0ad66f26d712e 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -500,7 +500,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                new_loan);
 
         // Should only be called for loans that are in scope at the same time.
-        assert!(self.bccx.region_scope_tree.scopes_intersect(old_loan.kill_scope,
+        debug_assert!(self.bccx.region_scope_tree.scopes_intersect(old_loan.kill_scope,
                                                        new_loan.kill_scope));
 
         let err_old_new = self.report_error_if_loan_conflicts_with_restriction(
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 7ce6863a7c986..01f1bbac5e25f 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -62,10 +62,10 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte
     match tcx.hir.get(parent) {
         NodeExpr(ref e) => {
             // the enclosing expression must be a `match` or something else
-            assert!(match e.node {
-                        ExprKind::Match(..) => true,
-                        _ => return PatternSource::Other,
-                    });
+            debug_assert!(match e.node {
+                ExprKind::Match(..) => true,
+                _ => return PatternSource::Other,
+            });
             PatternSource::MatchExpr(e)
         }
         NodeLocal(local) => PatternSource::LetDecl(local),
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index d08814138719a..de73a882f1af1 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -520,7 +520,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
         if self.bccx.region_scope_tree.is_subscope_of(lexical_scope, loan_scope) {
             lexical_scope
         } else {
-            assert!(self.bccx.region_scope_tree.is_subscope_of(loan_scope, lexical_scope));
+            debug_assert!(self.bccx.region_scope_tree.is_subscope_of(loan_scope, lexical_scope));
             loan_scope
         }
     }
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index aef8b58fa8bfa..02ec884ca47ee 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -90,7 +90,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
 fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
     -> Lrc<BorrowCheckResult>
 {
-    assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
+    debug_assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
 
     debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
 
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 44982eee86b3c..cbdf9f5863a35 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -352,7 +352,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
 
         let mut inputs = sig.inputs();
         let extra_args = if sig.abi == RustCall {
-            assert!(!sig.variadic && extra_args.is_empty());
+            debug_assert!(!sig.variadic && extra_args.is_empty());
 
             match sig.inputs().last().unwrap().sty {
                 ty::TyTuple(ref tupled_arguments) => {
@@ -365,7 +365,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
                 }
             }
         } else {
-            assert!(sig.variadic || extra_args.is_empty());
+            debug_assert!(sig.variadic || extra_args.is_empty());
             extra_args
         };
 
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index 845a66c6e4436..9248157fb4f83 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -1320,7 +1320,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
             _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
-                assert!(compiler_builtins.is_none());
+                debug_assert!(compiler_builtins.is_none());
                 compiler_builtins = Some(cnum);
             }
             Linkage::NotLinked |
@@ -1537,7 +1537,7 @@ fn add_upstream_rust_crates(cmd: &mut dyn Linker,
     fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
         // If we're performing LTO, then it should have been previously required
         // that all upstream rust dependencies were available in an rlib format.
-        assert!(!is_full_lto_enabled(sess));
+        debug_assert!(!is_full_lto_enabled(sess));
 
         // Just need to tell the linker about where the library lives and
         // what its name is
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 209c3a23c5cc3..553ed6d4c0ce8 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -541,7 +541,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
                 true
             };
 
-            if config.verify_llvm_ir { assert!(addpass("verify")); }
+            if config.verify_llvm_ir { debug_assert!(addpass("verify")); }
             if !config.no_prepopulate_passes {
                 llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
                 llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
@@ -1728,8 +1728,8 @@ fn start_executing_work(tcx: TyCtxt,
                 if work_items.len() == 0 &&
                    running == 0 &&
                    main_thread_worker_state == MainThreadWorkerState::Idle {
-                    assert!(!started_lto);
-                    assert!(needs_lto.len() > 0);
+                    debug_assert!(!started_lto);
+                    debug_assert!(needs_lto.len() > 0);
                     started_lto = true;
                     let modules = mem::replace(&mut needs_lto, Vec::new());
                     for (work, cost) in generate_lto_work(&cgcx, modules) {
@@ -1880,17 +1880,17 @@ fn start_executing_work(tcx: TyCtxt,
                             compiled_modules.push(compiled_module);
                         }
                         ModuleKind::Metadata => {
-                            assert!(compiled_metadata_module.is_none());
+                            debug_assert!(compiled_metadata_module.is_none());
                             compiled_metadata_module = Some(compiled_module);
                         }
                         ModuleKind::Allocator => {
-                            assert!(compiled_allocator_module.is_none());
+                            debug_assert!(compiled_allocator_module.is_none());
                             compiled_allocator_module = Some(compiled_module);
                         }
                     }
                 }
                 Message::NeedsLTO { result, worker_id } => {
-                    assert!(!started_lto);
+                    debug_assert!(!started_lto);
                     if main_thread_worker_state == MainThreadWorkerState::LLVMing {
                         main_thread_worker_state = MainThreadWorkerState::Idle;
                     } else {
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 8278b443a4c83..2dff63529bc5d 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -232,13 +232,13 @@ pub fn unsize_thin_ptr(
          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) |
         (&ty::TyRawPtr(ty::TypeAndMut { ty: a, .. }),
          &ty::TyRawPtr(ty::TypeAndMut { ty: b, .. })) => {
-            assert!(bx.cx.type_is_sized(a));
+            debug_assert!(bx.cx.type_is_sized(a));
             let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
             (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
         }
         (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
-            assert!(bx.cx.type_is_sized(a));
+            debug_assert!(bx.cx.type_is_sized(a));
             let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
             (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
         }
@@ -664,7 +664,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
         return metadata;
     }
 
-    assert!(kind == MetadataKind::Compressed);
+    debug_assert!(kind == MetadataKind::Compressed);
     let mut compressed = tcx.metadata_encoding_version();
     DeflateEncoder::new(&mut compressed, Compression::fast())
         .write_all(&metadata.raw_data).unwrap();
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index b174cd8c7ac76..79569f2f586bf 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1130,8 +1130,8 @@ impl Builder<'a, 'll, 'tcx> {
             fn_ty = fn_ty.element_type();
         }
 
-        assert!(fn_ty.kind() == llvm::TypeKind::Function,
-                "builder::{} not passed a function, but {:?}", typ, fn_ty);
+        debug_assert!(fn_ty.kind() == llvm::TypeKind::Function,
+                      "builder::{} not passed a function, but {:?}", typ, fn_ty);
 
         let param_tys = fn_ty.func_params();
 
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index e64dedac55a24..5875b6dca65a8 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -43,9 +43,9 @@ pub fn get_fn(
 
     debug!("get_fn(instance={:?})", instance);
 
-    assert!(!instance.substs.needs_infer());
-    assert!(!instance.substs.has_escaping_regions());
-    assert!(!instance.substs.has_param_types());
+    debug_assert!(!instance.substs.needs_infer());
+    debug_assert!(!instance.substs.has_escaping_regions());
+    debug_assert!(!instance.substs.has_param_types());
 
     let fn_ty = instance.ty(cx.tcx);
     if let Some(&llfn) = cx.instances.borrow().get(&instance) {
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 51fc610408b52..8b9503071e207 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -170,7 +170,7 @@ pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
     let bit_size = cx.data_layout().pointer_size.bits();
     if bit_size < 64 {
         // make sure it doesn't overflow
-        assert!(i < (1<<bit_size));
+        debug_assert!(i < (1<<bit_size));
     }
 
     C_uint(cx.isize_ty, i)
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 72ff65361cada..42a64a6c01cb3 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -115,10 +115,10 @@ pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
     let defined_in_current_codegen_unit = cx.codegen_unit
                                             .items()
                                             .contains_key(&MonoItem::Static(def_id));
-    assert!(!defined_in_current_codegen_unit,
-            "consts::get_static() should always hit the cache for \
-             statics defined in the same CGU, but did not for `{:?}`",
-             def_id);
+    debug_assert!(!defined_in_current_codegen_unit,
+                  "consts::get_static() should always hit the cache for \
+                   statics defined in the same CGU, but did not for `{:?}`",
+                  def_id);
 
     let ty = instance.ty(cx.tcx);
     let sym = cx.tcx.symbol_name(instance).as_str();
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 11f8e75831eed..1851cc9dde93f 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -395,7 +395,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
         }
 
         let tcx = self.tcx;
-        assert!(self.sess().target.target.options.custom_unwind_resume);
+        debug_assert!(self.sess().target.target.options.custom_unwind_resume);
         if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
             let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
             unwresume.set(Some(llfn));
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 143b122a5a172..ac3092a3b70ad 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -493,7 +493,7 @@ pub fn declare_local(
     variable_kind: VariableKind,
     span: Span,
 ) {
-    assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
+    debug_assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
     let cx = bx.cx;
 
     let file = span_start(cx, span).file;
diff --git a/src/librustc_codegen_llvm/glue.rs b/src/librustc_codegen_llvm/glue.rs
index 37ce51da77823..4a1619c34c6b0 100644
--- a/src/librustc_codegen_llvm/glue.rs
+++ b/src/librustc_codegen_llvm/glue.rs
@@ -53,7 +53,7 @@ pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Opt
             // First get the size of all statically known fields.
             // Don't use size_of because it also rounds up to alignment, which we
             // want to avoid, as the unsized field's alignment could be smaller.
-            assert!(!t.is_simd());
+            debug_assert!(!t.is_simd());
             let layout = cx.layout_of(t);
             debug!("DST {} layout: {:?}", t, layout);
 
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 06a5c34a4cae0..5caeb89dbfed7 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -602,7 +602,7 @@ pub fn codegen_intrinsic_call(
                         // This assumes the type is "simple", i.e. no
                         // destructors, and the contents are SIMD
                         // etc.
-                        assert!(!bx.cx.type_needs_drop(arg.layout.ty));
+                        debug_assert!(!bx.cx.type_needs_drop(arg.layout.ty));
                         let (ptr, align) = match arg.val {
                             OperandValue::Ref(ptr, align) => (ptr, align),
                             _ => bug!()
@@ -654,7 +654,7 @@ pub fn codegen_intrinsic_call(
             match *intr.output {
                 intrinsics::Type::Aggregate(flatten, ref elems) => {
                     // the output is a tuple so we need to munge it properly
-                    assert!(!flatten);
+                    debug_assert!(!flatten);
 
                     for i in 0..elems.len() {
                         let dest = result.project_field(bx, i);
@@ -1368,8 +1368,8 @@ fn generic_simd_intrinsic(
                 unreachable!();
             }
         };
-        assert!(pointer_count > 0);
-        assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
+        debug_assert!(pointer_count > 0);
+        debug_assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
         assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
 
         // The element type of the third argument must be a signed integer type of any width:
@@ -1465,8 +1465,8 @@ fn generic_simd_intrinsic(
                 unreachable!();
             }
         };
-        assert!(pointer_count > 0);
-        assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
+        debug_assert!(pointer_count > 0);
+        debug_assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx)));
         assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
 
         // The element type of the third argument must be a signed integer type of any width:
diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs
index 558d2a2bc87b3..0861cf062144d 100644
--- a/src/librustc_codegen_llvm/llvm/mod.rs
+++ b/src/librustc_codegen_llvm/llvm/mod.rs
@@ -223,8 +223,10 @@ pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
 pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
     unsafe {
-        assert!(index < LLVMCountParams(llfn),
-            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
+        debug_assert!(index < LLVMCountParams(llfn),
+                      "out of bounds argument access: {} out of {} arguments",
+                      index,
+                      LLVMCountParams(llfn));
         LLVMGetParam(llfn, index)
     }
 }
diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs
index 684ecfaeec8f1..9effed8f5cd48 100644
--- a/src/librustc_codegen_llvm/mir/block.rs
+++ b/src/librustc_codegen_llvm/mir/block.rs
@@ -873,7 +873,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
                 LocalRef::Operand(None) => {
                     let dst_layout = bx.cx.layout_of(self.monomorphized_place_ty(dst));
-                    assert!(!dst_layout.ty.has_erasable_regions());
+                    debug_assert!(!dst_layout.ty.has_erasable_regions());
                     let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
                     place.storage_live(bx);
                     self.codegen_transmute_into(bx, src, place);
@@ -882,7 +882,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                     self.locals[index] = LocalRef::Operand(Some(op));
                 }
                 LocalRef::Operand(Some(op)) => {
-                    assert!(op.layout.is_zst(),
+                    debug_assert!(op.layout.is_zst(),
                             "assigning to initialized SSAtemp");
                 }
             }
diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs
index 341ed9df64b59..de75a9a40f0cb 100644
--- a/src/librustc_codegen_llvm/mir/constant.rs
+++ b/src/librustc_codegen_llvm/mir/constant.rs
@@ -65,7 +65,7 @@ pub fn scalar_to_llvm(
                     callee::get_fn(cx, fn_instance)
                 }
                 Some(AllocType::Static(def_id)) => {
-                    assert!(cx.tcx.is_static(def_id).is_some());
+                    debug_assert!(cx.tcx.is_static(def_id).is_some());
                     consts::get_static(cx, def_id)
                 }
                 None => bug!("missing allocation {:?}", ptr.alloc_id),
diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs
index 8cdd0398eff96..2dc4389bb3cf1 100644
--- a/src/librustc_codegen_llvm/mir/mod.rs
+++ b/src/librustc_codegen_llvm/mir/mod.rs
@@ -248,7 +248,7 @@ pub fn codegen_mir(
         locals: IndexVec::new(),
         debug_context,
         param_substs: {
-            assert!(!instance.substs.needs_infer());
+            debug_assert!(!instance.substs.needs_infer());
             instance.substs
         },
     };
@@ -262,7 +262,7 @@ pub fn codegen_mir(
         let mut allocate_local = |local| {
             let decl = &mir.local_decls[local];
             let layout = bx.cx.layout_of(fx.monomorphize(&decl.ty));
-            assert!(!layout.ty.has_erasable_regions());
+            debug_assert!(!layout.ty.has_erasable_regions());
 
             if let Some(name) = decl.name {
                 // User variable
diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs
index 1296f5e4b144e..f9aac528c695d 100644
--- a/src/librustc_codegen_llvm/mir/operand.rs
+++ b/src/librustc_codegen_llvm/mir/operand.rs
@@ -68,7 +68,7 @@ impl fmt::Debug for OperandRef<'ll, 'tcx> {
 impl OperandRef<'ll, 'tcx> {
     pub fn new_zst(cx: &CodegenCx<'ll, 'tcx>,
                    layout: TyLayout<'tcx>) -> OperandRef<'ll, 'tcx> {
-        assert!(layout.is_zst());
+        debug_assert!(layout.is_zst());
         OperandRef {
             val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
             layout
diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs
index 02b5c27840eab..881622c98efad 100644
--- a/src/librustc_codegen_llvm/mir/rvalue.rs
+++ b/src/librustc_codegen_llvm/mir/rvalue.rs
@@ -167,7 +167,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
             }
 
             _ => {
-                assert!(self.rvalue_creates_operand(rvalue));
+                debug_assert!(self.rvalue_creates_operand(rvalue));
                 let (bx, temp) = self.codegen_rvalue_operand(bx, rvalue);
                 temp.val.store(&bx, dest);
                 bx
@@ -180,7 +180,9 @@ impl FunctionCx<'a, 'll, 'tcx> {
                                 rvalue: &mir::Rvalue<'tcx>)
                                 -> (Builder<'a, 'll, 'tcx>, OperandRef<'ll, 'tcx>)
     {
-        assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);
+        debug_assert!(self.rvalue_creates_operand(rvalue),
+                      "cannot codegen {:?} to operand",
+                      rvalue);
 
         match *rvalue {
             mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
@@ -221,7 +223,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                         operand.val
                     }
                     mir::CastKind::Unsize => {
-                        assert!(cast.is_llvm_scalar_pair());
+                        debug_assert!(cast.is_llvm_scalar_pair());
                         match operand.val {
                             OperandValue::Pair(lldata, llextra) => {
                                 // unsize from a fat pointer - this is a
@@ -265,7 +267,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                         }
                     }
                     mir::CastKind::Misc => {
-                        assert!(cast.is_llvm_immediate());
+                        debug_assert!(cast.is_llvm_immediate());
                         let ll_t_out = cast.immediate_llvm_type(bx.cx);
                         if operand.layout.abi == layout::Abi::Uninhabited {
                             return (bx, OperandRef {
@@ -462,7 +464,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
             }
 
             mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
-                assert!(bx.cx.type_is_sized(ty));
+                debug_assert!(bx.cx.type_is_sized(ty));
                 let val = C_usize(bx.cx, bx.cx.size_of(ty).bytes());
                 let tcx = bx.tcx();
                 (bx, OperandRef {
@@ -867,7 +869,7 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
         let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
         assert_eq!(rounded_min.status, Status::OK);
         let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
-        assert!(rounded_max.value.is_finite());
+        debug_assert!(rounded_max.value.is_finite());
         (rounded_min.value.to_bits(), rounded_max.value.to_bits())
     }
     fn int_max(signed: bool, int_ty: &Type) -> u128 {
diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs
index a528008e3b4bd..92e4b5dc807e5 100644
--- a/src/librustc_codegen_llvm/mono_item.rs
+++ b/src/librustc_codegen_llvm/mono_item.rs
@@ -151,8 +151,8 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                           linkage: Linkage,
                           visibility: Visibility,
                           symbol_name: &str) {
-    assert!(!instance.substs.needs_infer() &&
-            !instance.substs.has_param_types());
+    debug_assert!(!instance.substs.needs_infer() &&
+                  !instance.substs.has_param_types());
 
     let mono_ty = instance.ty(cx.tcx);
     let attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index 5fd4f15acd157..0f2ef9a191b68 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -131,7 +131,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         let target_offset = layout.fields.offset(i as usize);
         debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?}",
             i, field, offset, target_offset);
-        assert!(target_offset >= offset);
+        debug_assert!(target_offset >= offset);
         let padding = target_offset - offset;
         let padding_align = layout.align.min(prev_align).min(field.align);
         assert_eq!(offset.abi_align(padding_align) + padding, target_offset);
@@ -153,7 +153,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
                padding, offset, layout.size);
         result.push(Type::padding_filler(cx, padding, padding_align));
-        assert!(result.len() == 1 + field_count * 2);
+        debug_assert!(result.len() == 1 + field_count * 2);
     } else {
         debug!("struct_llfields: offset: {:?} stride: {:?}",
                offset, layout.size);
@@ -284,7 +284,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
 
         debug!("llvm_type({:#?})", self);
 
-        assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty);
+        debug_assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty);
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index ac71ecff96457..058dce433599a 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -161,7 +161,7 @@ fn get_symbol_hash<'a, 'tcx>(
         // Include the main item-type. Note that, in this case, the
         // assertions about `needs_subst` may not hold, but this item-type
         // ought to be the same for every reference anyway.
-        assert!(!item_type.has_erasable_regions());
+        debug_assert!(!item_type.has_erasable_regions());
         hcx.while_hashing_spans(false, |hcx| {
             hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                 item_type.hash_stable(hcx, &mut hasher);
@@ -176,8 +176,8 @@ fn get_symbol_hash<'a, 'tcx>(
         }
 
         // also include any type parameters (for generic items)
-        assert!(!substs.has_erasable_regions());
-        assert!(!substs.needs_subst());
+        debug_assert!(!substs.has_erasable_regions());
+        debug_assert!(!substs.needs_subst());
         substs.hash_stable(&mut hcx, &mut hasher);
 
         let is_generic = substs.types().next().is_some();
diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs
index 56bb961324210..b5b780eb85014 100644
--- a/src/librustc_data_structures/array_vec.rs
+++ b/src/librustc_data_structures/array_vec.rs
@@ -129,8 +129,8 @@ impl<A: Array> ArrayVec<A> {
             Excluded(&n) => n,
             Unbounded    => len,
         };
-        assert!(start <= end);
-        assert!(end <= len);
+        debug_assert!(start <= end);
+        debug_assert!(end <= len);
 
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs
index b8f191c2f57d8..ff87d482edfb3 100644
--- a/src/librustc_data_structures/bitslice.rs
+++ b/src/librustc_data_structures/bitslice.rs
@@ -92,7 +92,7 @@ pub fn bits_to_string(words: &[Word], bits: usize) -> String {
             let remain = bits - i;
             // If less than a byte remains, then mask just that many bits.
             let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF };
-            assert!(mask <= 0xFF);
+            debug_assert!(mask <= 0xFF);
             let byte = v & mask;
 
             result.push_str(&format!("{}{:02x}", sep, byte));
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index 04d6cb5e2a6d2..3717773f0100e 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -95,7 +95,7 @@ impl<C: Idx> BitVector<C> {
 
     #[inline]
     pub fn merge(&mut self, all: &BitVector<C>) -> bool {
-        assert!(self.data.len() == all.data.len());
+        debug_assert!(self.data.len() == all.data.len());
         let mut changed = false;
         for (i, j) in self.data.iter_mut().zip(&all.data) {
             let value = *i;
diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs
index d134fad2855bb..120379d0f1134 100644
--- a/src/librustc_data_structures/graph/dominators/mod.rs
+++ b/src/librustc_data_structures/graph/dominators/mod.rs
@@ -122,12 +122,12 @@ impl<Node: Idx> Dominators<Node> {
     }
 
     pub fn immediate_dominator(&self, node: Node) -> Node {
-        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
+        debug_assert!(self.is_reachable(node), "node {:?} is not reachable", node);
         self.immediate_dominators[node].unwrap()
     }
 
     pub fn dominators(&self, node: Node) -> Iter<Node> {
-        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
+        debug_assert!(self.is_reachable(node), "node {:?} is not reachable", node);
         Iter {
             dominators: self,
             node: Some(node),
diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs
index a989a54010222..c8b01362d65b3 100644
--- a/src/librustc_data_structures/graph/scc/mod.rs
+++ b/src/librustc_data_structures/graph/scc/mod.rs
@@ -304,7 +304,7 @@ where
                     min_depth: successor_min_depth,
                 } => {
                     // Track the minimum depth we can reach.
-                    assert!(successor_min_depth <= depth);
+                    debug_assert!(successor_min_depth <= depth);
                     if successor_min_depth < min_depth {
                         debug!(
                             "walk_unvisited_node: node = {:?} successor_min_depth = {:?}",
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index c358f2f852e18..a6cc7d61d7843 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -43,7 +43,7 @@ impl Idx for usize {
 
 impl Idx for u32 {
     #[inline]
-    fn new(idx: usize) -> Self { assert!(idx <= u32::MAX as usize); idx as u32 }
+    fn new(idx: usize) -> Self { debug_assert!(idx <= u32::MAX as usize); idx as u32 }
     #[inline]
     fn index(self) -> usize { self as usize }
 }
@@ -85,7 +85,7 @@ macro_rules! newtype_index {
         impl Idx for $type {
             #[inline]
             fn new(value: usize) -> Self {
-                assert!(value < ($max) as usize);
+                debug_assert!(value < ($max) as usize);
                 $type(value as u32)
             }
 
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 0d6cf260dcd98..4940f810707d7 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -236,7 +236,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             }
         }
         let successful_obligations = self.compress();
-        assert!(successful_obligations.is_empty());
+        debug_assert!(successful_obligations.is_empty());
         errors
     }
 
diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs
index d89bd22ec9637..0ecca67456f99 100644
--- a/src/librustc_data_structures/obligation_forest/node_index.rs
+++ b/src/librustc_data_structures/obligation_forest/node_index.rs
@@ -19,7 +19,7 @@ pub struct NodeIndex {
 impl NodeIndex {
     #[inline]
     pub fn new(value: usize) -> NodeIndex {
-        assert!(value < (u32::MAX as usize));
+        debug_assert!(value < (u32::MAX as usize));
         NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() }
     }
 
diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs
index b5f52d54ae471..70ed20f36a7e7 100644
--- a/src/librustc_data_structures/small_vec.rs
+++ b/src/librustc_data_structures/small_vec.rs
@@ -69,7 +69,7 @@ impl<A: Array> SmallVec<A> {
     }
 
     pub fn expect_one(self, err: &'static str) -> A::Element {
-        assert!(self.len() == 1, err);
+        debug_assert!(self.len() == 1, err);
         match self.0 {
             AccumulateVec::Array(arr) => arr.into_iter().next().unwrap(),
             AccumulateVec::Heap(vec) => vec.into_iter().next().unwrap(),
@@ -117,7 +117,7 @@ impl<A: Array> SmallVec<A> {
         // Reserve space for shifting elements to the right
         self.reserve(1);
 
-        assert!(index <= len);
+        debug_assert!(index <= len);
 
         unsafe {
             // infallible
diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs
index 6ee8c3579f543..8682703a5a584 100644
--- a/src/librustc_data_structures/snapshot_map/mod.rs
+++ b/src/librustc_data_structures/snapshot_map/mod.rs
@@ -96,8 +96,8 @@ impl<K, V> SnapshotMap<K, V>
     }
 
     fn assert_open_snapshot(&self, snapshot: &Snapshot) {
-        assert!(snapshot.len < self.undo_log.len());
-        assert!(match self.undo_log[snapshot.len] {
+        debug_assert!(snapshot.len < self.undo_log.len());
+        debug_assert!(match self.undo_log[snapshot.len] {
             UndoLog::OpenSnapshot => true,
             _ => false,
         });
@@ -143,11 +143,11 @@ impl<K, V> SnapshotMap<K, V>
         }
 
         let v = self.undo_log.pop().unwrap();
-        assert!(match v {
+        debug_assert!(match v {
             UndoLog::OpenSnapshot => true,
             _ => false,
         });
-        assert!(self.undo_log.len() == snapshot.len);
+        debug_assert!(self.undo_log.len() == snapshot.len);
     }
 
     fn reverse(&mut self, entry: UndoLog<K, V>) {
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index d4c6b1c2ced81..94111621f76e5 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -338,7 +338,7 @@ pub trait HashMapExt<K, V> {
 
 impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S> {
     fn insert_same(&mut self, key: K, value: V) {
-        self.entry(key).and_modify(|old| assert!(*old == value)).or_insert(value);
+        self.entry(key).and_modify(|old| debug_assert!(*old == value)).or_insert(value);
     }
 }
 
@@ -383,7 +383,7 @@ impl<T> Once<T> {
     pub fn try_set_same(&self, value: T) -> Option<T> where T: Eq {
         let mut lock = self.0.lock();
         if let Some(ref inner) = *lock {
-            assert!(*inner == value);
+            debug_assert!(*inner == value);
             return Some(value);
         }
         *lock = Some(value);
diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs
index 2ec85e1c27f1d..2169aeb6cb06f 100644
--- a/src/librustc_driver/profile/mod.rs
+++ b/src/librustc_driver/profile/mod.rs
@@ -90,8 +90,8 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
         match msg {
             ProfileQueriesMsg::Halt => return,
             ProfileQueriesMsg::Dump(params) => {
-                assert!(stack.len() == 0);
-                assert!(frame.parse_st == ParseState::Clear);
+                debug_assert!(stack.len() == 0);
+                debug_assert!(frame.parse_st == ParseState::Clear);
                 {
                     // write log of all messages
                     if params.dump_profq_msg_log {
diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs
index f31111e37ba08..04489bce134ba 100644
--- a/src/librustc_driver/profile/trace.rs
+++ b/src/librustc_driver/profile/trace.rs
@@ -46,14 +46,14 @@ pub struct QueryMetric {
 pub fn cons_of_query_msg(q: &trace::Query) -> String {
     let s = format!("{:?}", q.msg);
     let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
-    assert!(cons.len() > 0 && cons[0] != "");
+    debug_assert!(cons.len() > 0 && cons[0] != "");
     cons[0].to_string()
 }
 
 pub fn cons_of_key(k: &DepNode) -> String {
     let s = format!("{:?}", k);
     let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
-    assert!(cons.len() > 0 && cons[0] != "");
+    debug_assert!(cons.len() > 0 && cons[0] != "");
     cons[0].to_string()
 }
 
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index 795825f180c9d..78b62062a45d9 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -686,7 +686,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
     let lock_file_to_session_dir: FxHashMap<String, Option<String>> =
         lock_files.into_iter()
                   .map(|lock_file_name| {
-                        assert!(lock_file_name.ends_with(LOCK_FILE_EXT));
+                        debug_assert!(lock_file_name.ends_with(LOCK_FILE_EXT));
                         let dir_prefix_end = lock_file_name.len() - LOCK_FILE_EXT.len();
                         let session_dir = {
                             let dir_prefix = &lock_file_name[0 .. dir_prefix_end];
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 27221296ff31f..036c7fa413e65 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1040,7 +1040,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
                     // Reading from mere reservations of mutable-borrows is OK.
                     if !is_active(&this.dominators, borrow, context.loc) {
-                        assert!(allow_two_phase_borrow(&this.tcx, borrow.kind));
+                        debug_assert!(allow_two_phase_borrow(&this.tcx, borrow.kind));
                         return Control::Continue;
                     }
 
@@ -1428,7 +1428,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             let borrow = &borrow_set[borrow_index];
 
             // only mutable borrows should be 2-phase
-            assert!(match borrow.kind {
+            debug_assert!(match borrow.kind {
                 BorrowKind::Shared => false,
                 BorrowKind::Unique | BorrowKind::Mut { .. } => true,
             });
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 301999cc4a51e..255dc6d8f6374 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -525,7 +525,7 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cg, 'cx, 'tcx, 'gcx> {
                         // Reading from mere reservations of mutable-borrows is OK.
                         if !is_active(&this.dominators, borrow, context.loc) {
                             // If the borrow isn't active yet, reads don't invalidate it
-                            assert!(allow_two_phase_borrow(&this.infcx.tcx, borrow.kind));
+                            debug_assert!(allow_two_phase_borrow(&this.infcx.tcx, borrow.kind));
                             return Control::Continue;
                         }
 
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 973568a67f030..54eeaaef01b6d 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -434,7 +434,7 @@ fn live_variable_set(
         string.push_str(&format!("{:?}", local));
 
         if !regular.contains(&local) {
-            assert!(drops.contains(&local));
+            debug_assert!(drops.contains(&local));
             string.push_str(" (drop)");
         }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 8505d8e1ef39c..3378f3079fc88 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -59,7 +59,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> InternedString {
         debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
 
-        assert!(self.universal_regions.is_universal_region(fr));
+        debug_assert!(self.universal_regions.is_universal_region(fr));
 
         self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter, diag)
             .or_else(|| {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
index f1c3a7489ee8f..7a8c64b5df2ce 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/var_name.rs
@@ -24,7 +24,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr: RegionVid,
     ) -> Option<(Option<Symbol>, Span)> {
         debug!("get_var_name_and_span_for_region(fr={:?})", fr);
-        assert!(self.universal_regions.is_universal_region(fr));
+        debug_assert!(self.universal_regions.is_universal_region(fr));
 
         debug!("get_var_name_and_span_for_region: attempting upvar");
         self.get_upvar_index_for_region(tcx, fr)
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index afd4e2859aced..764cdeed58c15 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -671,8 +671,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // of the existing subject-region R. This should be a non-local, universal
         // region, which ensures it can be encoded in a `ClosureOutlivesRequirement`.
         let lower_bound_plus = self.non_local_universal_upper_bound(*lower_bound);
-        assert!(self.universal_regions.is_universal_region(lower_bound_plus));
-        assert!(
+        debug_assert!(self.universal_regions.is_universal_region(lower_bound_plus));
+        debug_assert!(
             !self
                 .universal_regions
                 .is_local_free_region(lower_bound_plus)
@@ -987,7 +987,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Because this free region must be in the ROOT universe, we
         // know it cannot contain any bound universes.
-        assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
+        debug_assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
         debug_assert!(
             self.scc_values
                 .subuniverses_contained_in(longer_fr_scc)
diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
index e4b1aacd34f71..f1bd84a7d3c52 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
@@ -114,8 +114,8 @@ impl UniversalRegionRelations<'tcx> {
     /// (See `TransitiveRelation::postdom_upper_bound` for details on
     /// the postdominating upper bound in general.)
     crate fn postdom_upper_bound(&self, fr1: RegionVid, fr2: RegionVid) -> RegionVid {
-        assert!(self.universal_regions.is_universal_region(fr1));
-        assert!(self.universal_regions.is_universal_region(fr2));
+        debug_assert!(self.universal_regions.is_universal_region(fr1));
+        debug_assert!(self.universal_regions.is_universal_region(fr2));
         *self
             .inverse_outlives
             .postdom_upper_bound(&fr1, &fr2)
@@ -158,7 +158,7 @@ impl UniversalRegionRelations<'tcx> {
     ) -> Option<RegionVid> {
         // This method assumes that `fr0` is one of the universally
         // quantified region variables.
-        assert!(self.universal_regions.is_universal_region(fr0));
+        debug_assert!(self.universal_regions.is_universal_region(fr0));
 
         let mut external_parents = vec![];
         let mut queue = vec![&fr0];
@@ -353,9 +353,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
 impl<'tcx> FreeRegionRelations<'tcx> for UniversalRegionRelations<'tcx> {
     fn sub_free_regions(&self, shorter: ty::Region<'tcx>, longer: ty::Region<'tcx>) -> bool {
         let shorter = shorter.to_region_vid();
-        assert!(self.universal_regions.is_universal_region(shorter));
+        debug_assert!(self.universal_regions.is_universal_region(shorter));
         let longer = longer.to_region_vid();
-        assert!(self.universal_regions.is_universal_region(longer));
+        debug_assert!(self.universal_regions.is_universal_region(longer));
         self.outlives(longer, shorter)
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index af42667016780..f63281cc118e6 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -59,7 +59,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             self.equate_normalized_input_or_output(normalized_input_ty, mir_input_ty);
         }
 
-        assert!(
+        debug_assert!(
             mir.yield_ty.is_some() && universal_regions.yield_ty.is_some()
                 || mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
         );
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index a18e2368bf724..322d44a6d26c1 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -412,7 +412,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 let base_ty = self.sanitize_place(&proj.base, location, base_context);
                 if let PlaceTy::Ty { ty } = base_ty {
                     if ty.references_error() {
-                        assert!(self.errors_reported);
+                        debug_assert!(self.errors_reported);
                         return PlaceTy::Ty {
                             ty: self.tcx().types.err,
                         };
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 765c4cf906e68..7c5b7ba6f7bf3 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -484,7 +484,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
                 // `identity_substs`, we will get only those regions
                 // that correspond to early-bound regions declared on
                 // the `closure_base_def_id`.
-                assert!(substs.len() >= identity_substs.len());
+                debug_assert!(substs.len() >= identity_substs.len());
                 assert_eq!(substs.regions().count(), identity_substs.regions().count());
                 substs
             }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 68009e962a302..15f31c628ad67 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -519,7 +519,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     // Helper to get the minimum value of the appropriate type
     fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
-        assert!(ty.is_signed());
+        debug_assert!(ty.is_signed());
         let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap());
         let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits();
         let n = 1 << (bits - 1);
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 59a7f49af8074..439d2a4e653ef 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -236,7 +236,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     let mut args = args.into_iter();
                     let ptr = args.next().expect("0 arguments to `move_val_init`");
                     let val = args.next().expect("1 argument to `move_val_init`");
-                    assert!(args.next().is_none(), ">2 arguments to `move_val_init`");
+                    debug_assert!(args.next().is_none(), ">2 arguments to `move_val_init`");
 
                     let ptr = this.hir.mirror(ptr);
                     let ptr_ty = ptr.ty;
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 6a447d81dc3cb..fd11a2678015a 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             // The region is unknown at this point; we rely on NLL
             // inference to find an appropriate one. Therefore you can
             // only use this when NLL is turned on.
-            assert!(tcx.use_mir_borrowck());
+            debug_assert!(tcx.use_mir_borrowck());
             let borrowed_input =
                 Rvalue::Ref(tcx.types.re_empty, BorrowKind::Shared, discriminant_place.clone());
             let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx);
@@ -332,8 +332,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                             has_guard: ArmHasGuard,
                             opt_match_place: Option<(Option<&Place<'tcx>>, Span)>)
                             -> Option<SourceScope> {
-        assert!(!(visibility_scope.is_some() && lint_level.is_explicit()),
-                "can't have both a visibility and a lint scope at the same time");
+        debug_assert!(!(visibility_scope.is_some() && lint_level.is_explicit()),
+                      "can't have both a visibility and a lint scope at the same time");
         let mut scope = self.source_scope;
         let num_patterns = patterns.len();
         self.visit_bindings(&patterns[0], &mut |this, mutability, name, mode, var, span, ty| {
@@ -837,7 +837,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                                           c,
                                                           &mut target_candidates))
                       .count();
-        assert!(tested_candidates > 0); // at least the last candidate ought to be tested
+        debug_assert!(tested_candidates > 0); // at least the last candidate ought to be tested
         debug!("tested_candidates: {}", tested_candidates);
         debug!("untested_candidates: {}", candidates.len() - tested_candidates);
 
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs
index cfd9100fc6ae7..63ff228164b91 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir/build/matches/util.rs
@@ -35,7 +35,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                      opt_slice: Option<&'pat Pattern<'tcx>>,
                                      suffix: &'pat [Pattern<'tcx>]) {
         let min_length = prefix.len() + suffix.len();
-        assert!(min_length < u32::MAX as usize);
+        debug_assert!(min_length < u32::MAX as usize);
         let min_length = min_length as u32;
 
         match_pairs.extend(
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 2dc5138c6f082..6518bcc40b149 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         self.breakable_scopes.push(scope);
         let res = f(self);
         let breakable_scope = self.breakable_scopes.pop().unwrap();
-        assert!(breakable_scope.region_scope == region_scope);
+        debug_assert!(breakable_scope.region_scope == region_scope);
         res
     }
 
@@ -413,7 +413,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 span_bug!(span, "region_scope {:?} does not enclose", region_scope)
             });
         let len = self.scopes.len();
-        assert!(scope_count < len, "should not use `exit_scope` to pop ALL scopes");
+        debug_assert!(scope_count < len, "should not use `exit_scope` to pop ALL scopes");
 
         // If we are emitting a `drop` statement, we need to have the cached
         // diverge cleanup pads ready in case that drop panics.
@@ -565,8 +565,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn region_scope_of_return_scope(&self) -> region::Scope {
         // The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
         // We want `scopes[1]`, which is the `ParameterScope`.
-        assert!(self.scopes.len() >= 2);
-        assert!(match self.scopes[1].region_scope.data() {
+        debug_assert!(self.scopes.len() >= 2);
+        debug_assert!(match self.scopes[1].region_scope.data() {
             region::ScopeData::Arguments(_) => true,
             _ => false,
         });
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index ee3bba840c67b..2e71d8097dc56 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -339,7 +339,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
         drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.mdpe,
             |path, s| {
-                assert!(s == DropFlagState::Present);
+                debug_assert!(s == DropFlagState::Present);
                 entry_set.add(&path);
             });
     }
@@ -394,7 +394,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
         drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.mdpe,
             |path, s| {
-                assert!(s == DropFlagState::Present);
+                debug_assert!(s == DropFlagState::Present);
                 entry_set.remove(&path);
             });
     }
@@ -448,7 +448,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc
         drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.mdpe,
             |path, s| {
-                assert!(s == DropFlagState::Present);
+                debug_assert!(s == DropFlagState::Present);
                 entry_set.add(&path);
             });
     }
@@ -559,7 +559,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
                               move_data,
                               move_data.rev_lookup.find(dest_place),
                               |mpi| for moi in &path_map[mpi] {
-                                  assert!(moi.index() < bits_per_block);
+                                  debug_assert!(moi.index() < bits_per_block);
                                   in_out.remove(&moi);
                               });
     }
@@ -655,7 +655,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> {
             statement_index: self.mir[call_bb].statements.len(),
         };
         for init_index in &init_loc_map[call_loc] {
-            assert!(init_index.index() < bits_per_block);
+            debug_assert!(init_index.index() < bits_per_block);
             in_out.add(init_index);
         }
     }
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 4227f0bcd362d..e4dbfceeeb880 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -523,7 +523,7 @@ impl<'a, E:Idx> BlockSets<'a, E> {
             let j = j.borrow();
             let retval = self.gen_set.add(j);
             self.kill_set.remove(j);
-            assert!(retval);
+            debug_assert!(retval);
         }
     }
 
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 5d45955771185..cd7c73c5624e4 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -109,7 +109,7 @@ impl<'a, 'tcx> fmt::Debug for Matrix<'a, 'tcx> {
         }).collect();
 
         let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0);
-        assert!(m.iter().all(|row| row.len() == column_count));
+        debug_assert!(m.iter().all(|row| row.len() == column_count));
         let column_widths: Vec<usize> = (0..column_count).map(|col| {
             pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
         }).collect();
@@ -185,7 +185,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
                             .builtin_deref(true)
                             .and_then(|t| t.ty.builtin_index())
                             .map_or(false, |t| t == tcx.types.u8);
-                        assert!(is_array_ptr);
+                        debug_assert!(is_array_ptr);
                         let alloc = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
                         assert_eq!(ptr.offset.bytes(), 0);
                         // FIXME: check length
@@ -265,7 +265,7 @@ impl<'tcx> Constructor<'tcx> {
         match self {
             &Variant(vid) => adt.variant_index_with_id(vid),
             &Single => {
-                assert!(!adt.is_enum());
+                debug_assert!(!adt.is_enum());
                 0
             }
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt)
@@ -615,7 +615,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         }
     };
 
-    assert!(rows.iter().all(|r| r.len() == v.len()));
+    debug_assert!(rows.iter().all(|r| r.len() == v.len()));
 
     let pcx = PatternContext {
         // TyErr is used to represent the type of wildcard patterns matching
@@ -937,7 +937,7 @@ fn slice_pat_covered_by_constructor<'tcx>(
                     .builtin_deref(true)
                     .and_then(|t| t.ty.builtin_index())
                     .map_or(false, |t| t == tcx.types.u8);
-                assert!(is_array_ptr);
+                debug_assert!(is_array_ptr);
                 tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).bytes.as_ref()
             } else {
                 bug!("unexpected non-ptr ConstantValue")
@@ -1074,7 +1074,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                             .builtin_deref(true)
                             .and_then(|t| t.ty.builtin_index())
                             .map_or(false, |t| t == cx.tcx.types.u8);
-                        assert!(is_array_ptr);
+                        debug_assert!(is_array_ptr);
                         let data_len = cx.tcx
                             .alloc_map
                             .lock()
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 873fef75bb9eb..6ccc7dde61973 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -89,8 +89,8 @@ pub fn value_to_const_value<'tcx>(
             Value::ByRef(ptr, align) => {
                 let ptr = ptr.to_ptr().unwrap();
                 let alloc = ecx.memory.get(ptr.alloc_id)?;
-                assert!(alloc.align.abi() >= align.abi());
-                assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
+                debug_assert!(alloc.align.abi() >= align.abi());
+                debug_assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
                 let mut alloc = alloc.clone();
                 alloc.align = align;
                 let alloc = ecx.tcx.intern_const_alloc(alloc);
@@ -148,7 +148,7 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>(
         mir = &mir.promoted[index];
     }
     let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
-    assert!(!layout.is_unsized());
+    debug_assert!(!layout.is_unsized());
     let ptr = ecx.memory.allocate(
         layout.size,
         layout.align,
@@ -165,7 +165,7 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>(
     let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
     let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
     trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
-    assert!(mir.arg_count == 0);
+    debug_assert!(mir.arg_count == 0);
     ecx.push_stack_frame(
         cid.instance,
         mir.span,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index c6c1a1d1ebb22..8d56789cefb00 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -350,7 +350,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
     }
 
     pub fn alloc_ptr(&mut self, layout: TyLayout<'tcx>) -> EvalResult<'tcx, Pointer> {
-        assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
+        debug_assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
 
         self.memory.allocate(layout.size, layout.align, MemoryKind::Stack)
     }
@@ -369,7 +369,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
 
     #[inline]
     pub fn cur_frame(&self) -> usize {
-        assert!(self.stack.len() > 0);
+        debug_assert!(self.stack.len() > 0);
         self.stack.len() - 1
     }
 
@@ -466,7 +466,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                     // Don't use type_of::sizing_type_of because that expects t to be sized,
                     // and it also rounds up to alignment, which we want to avoid,
                     // as the unsized field's alignment could be smaller.
-                    assert!(!ty.is_simd());
+                    debug_assert!(!ty.is_simd());
                     debug!("DST {} layout: {:?}", ty, layout);
 
                     let sized_size = layout.fields.offset(layout.fields.count() - 1);
@@ -779,7 +779,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             NullaryOp(mir::NullOp::SizeOf, ty) => {
                 let ty = self.monomorphize(ty, self.substs());
                 let layout = self.layout_of(ty)?;
-                assert!(!layout.is_unsized(),
+                debug_assert!(!layout.is_unsized(),
                         "SizeOf nullary MIR operator called for unsized type");
                 let defined = self.memory.pointer_size().bits() as u8;
                 self.write_scalar(
@@ -953,8 +953,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                 let variants_end = *niche_variants.end() as u128;
                 match raw_discr {
                     Scalar::Ptr(_) => {
-                        assert!(niche_start == 0);
-                        assert!(variants_start == variants_end);
+                        debug_assert!(niche_start == 0);
+                        debug_assert!(variants_start == variants_end);
                         dataful_variant as u128
                     },
                     Scalar::Bits { bits: raw_discr, defined } => {
@@ -1846,7 +1846,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             // Potentially-fat pointers.
             ty::TyRef(_, pointee, _) |
             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
-                assert!(i < 2);
+                debug_assert!(i < 2);
 
                 // Reuse the fat *T type as its own thin pointer data field.
                 // This provides information about e.g. DST struct pointees
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 6e5cfe3bb3ee7..a7a6da4a35f07 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -330,7 +330,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
         };
         self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
             // no need to report anything, the const_eval call takes care of that for statics
-            assert!(self.tcx.is_static(def_id).is_some());
+            debug_assert!(self.tcx.is_static(def_id).is_some());
             EvalErrorKind::ReferencedConstant(err).into()
         }).map(|val| {
             self.tcx.const_value_to_allocation(val)
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 0c921f66198eb..539fb9ec4c607 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -41,7 +41,7 @@ pub fn sign_extend<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, value: u128, ty: Ty<'t
     let param_env = ParamEnv::empty();
     let layout = tcx.layout_of(param_env.and(ty)).map_err(|layout| EvalErrorKind::Layout(layout))?;
     let size = layout.size.bits();
-    assert!(layout.abi.is_signed());
+    debug_assert!(layout.abi.is_signed());
     // sign extend
     let shift = 128 - size;
     // shift the unsigned value to the left
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 59bf2ae6c0fe7..434d44ae5cc93 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -147,7 +147,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 let offset = base_layout.fields.offset(field_index);
                 let ptr = base_ptr.ptr_offset(offset, self)?;
                 let align = align.min(base_layout.align).min(field.align);
-                assert!(!field.is_unsized());
+                debug_assert!(!field.is_unsized());
                 Value::ByRef(ptr, align)
             },
             Value::Scalar(val) => bug!("field access on non aggregate {:#?}, {:#?}", val, base_layout),
@@ -354,7 +354,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
 
         let (elem_ty, len) = base.elem_ty_and_len(outer_ty, self.tcx.tcx);
         let elem_size = self.layout_of(elem_ty)?.size;
-        assert!(
+        debug_assert!(
             n < len,
             "Tried to access element {} of array/slice with length {}",
             n,
@@ -432,7 +432,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
 
                 let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
                 let elem_size = self.layout_of(elem_ty)?.size;
-                assert!(n >= min_length as u64);
+                debug_assert!(n >= min_length as u64);
 
                 let index = if from_end {
                     n - u64::from(offset)
@@ -451,7 +451,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
 
                 let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
                 let elem_size = self.layout_of(elem_ty)?.size;
-                assert!(u64::from(from) <= n - u64::from(to));
+                debug_assert!(u64::from(from) <= n - u64::from(to));
                 let ptr = base_ptr.ptr_offset(elem_size * u64::from(from), &self)?;
                 // sublicing arrays produces arrays
                 let extra = if self.type_is_sized(base_ty) {
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index b6c7feda19fa8..6de0531e61187 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -21,7 +21,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
         debug!("get_vtable(trait_ref={:?})", trait_ref);
 
         let layout = self.layout_of(trait_ref.self_ty())?;
-        assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
+        debug_assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
         let size = layout.size.bytes();
         let align = layout.align.abi();
 
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 5f05783b15cce..f6661733027b4 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -249,7 +249,7 @@ impl<'tcx> InliningMap<'tcx> {
                           new_targets: I)
         where I: Iterator<Item=(MonoItem<'tcx>, bool)> + ExactSizeIterator
     {
-        assert!(!self.index.contains_key(&source));
+        debug_assert!(!self.index.contains_key(&source));
 
         let start_index = self.targets.len();
         let new_items_count = new_targets.len();
@@ -877,8 +877,8 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let source_fields = &source_adt_def.non_enum_variant().fields;
             let target_fields = &target_adt_def.non_enum_variant().fields;
 
-            assert!(coerce_index < source_fields.len() &&
-                    source_fields.len() == target_fields.len());
+            debug_assert!(coerce_index < source_fields.len() &&
+                          source_fields.len() == target_fields.len());
 
             find_vtable_types_for_unsizing(tcx,
                                            source_fields[coerce_index].ty(tcx,
@@ -903,13 +903,13 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                   trait_ty: Ty<'tcx>,
                                                   impl_ty: Ty<'tcx>,
                                                   output: &mut Vec<MonoItem<'tcx>>) {
-    assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
-            !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
+    debug_assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
+                  !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
 
     if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
         if let Some(principal) = trait_ty.principal() {
             let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
-            assert!(!poly_trait_ref.has_escaping_regions());
+            debug_assert!(!poly_trait_ref.has_escaping_regions());
 
             // Walk all methods of the trait, including those of its supertraits
             let methods = tcx.vtable_methods(poly_trait_ref);
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index bd0b2c6c278b1..f12c140cfbb06 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -490,7 +490,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<'tcx>,
                              target_cgu_count: usize,
                              crate_name: &str) {
-    assert!(target_cgu_count >= 1);
+    debug_assert!(target_cgu_count >= 1);
     let codegen_units = &mut initial_partitioning.codegen_units;
 
     // Note that at this point in time the `codegen_units` here may not be in a
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 9902fe98cc011..01af72cff9cb4 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -555,7 +555,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
                             trace!("storing {:?} to {:?}", value, local);
-                            assert!(self.places[local].is_none());
+                            debug_assert!(self.places[local].is_none());
                             self.places[local] = Some(value);
                         }
                     }
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 937d01a0c5e88..c3f12d9fe2a50 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -51,7 +51,7 @@ impl MirPass for ElaborateDrops {
                 // If we are in the migration path, we have already
                 // reported these errors as warnings to the user. So
                 // we will just ignore them here.
-                assert!(tcx.migrate_borrowck());
+                debug_assert!(tcx.migrate_borrowck());
                 move_data
             }
         };
@@ -441,7 +441,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 TerminatorKind::DropAndReplace { ref location, ref value,
                                                  target, unwind } =>
                 {
-                    assert!(!data.is_cleanup);
+                    debug_assert!(!data.is_cleanup);
 
                     self.elaborate_replace(
                         loc,
@@ -477,7 +477,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let bb = loc.block;
         let data = &self.mir[bb];
         let terminator = data.terminator();
-        assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");
+        debug_assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");
 
         let assign = Statement {
             kind: StatementKind::Assign(location.clone(), Rvalue::Use(value.clone())),
@@ -569,7 +569,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             if let TerminatorKind::Call {
                 destination: Some((ref place, tgt)), cleanup: Some(_), ..
             } = data.terminator().kind {
-                assert!(!self.patch.is_patched(bb));
+                debug_assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: tgt, statement_index: 0 };
                 let path = self.move_data().rev_lookup.find(place);
@@ -614,7 +614,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             // only want the former - the latter is handled
                             // by the elaboration code and must be done
                             // *after* the destination is dropped.
-                            assert!(self.patch.is_patched(bb));
+                            debug_assert!(self.patch.is_patched(bb));
                             allow_initializations = false;
                         }
                         TerminatorKind::Resume => {
@@ -623,7 +623,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             // a Goto; see `MirPatch::new`).
                         }
                         _ => {
-                            assert!(!self.patch.is_patched(bb));
+                            debug_assert!(!self.patch.is_patched(bb));
                         }
                     }
                 }
@@ -643,7 +643,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             if let TerminatorKind::Call {
                 destination: Some((ref place, _)), cleanup: None, ..
             } = data.terminator().kind {
-                assert!(!self.patch.is_patched(bb));
+                debug_assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: bb, statement_index: data.statements.len() };
                 let path = self.move_data().rev_lookup.find(place);
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 6a9258fe2c918..78271f4aa30d9 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -853,7 +853,7 @@ impl MirPass for StateTransform {
             return
         };
 
-        assert!(mir.generator_drop.is_none());
+        debug_assert!(mir.generator_drop.is_none());
 
         let def_id = source.def_id;
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 46fab544aafe9..93d8190ae171d 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -535,7 +535,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             let mut args = args.into_iter();
             let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
             let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
-            assert!(args.next().is_none());
+            debug_assert!(args.next().is_none());
 
             let tuple = Place::Local(tuple);
             let tuple_tys = if let ty::TyTuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 90dfebeef1b0c..6ce6fa2045da1 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -182,7 +182,7 @@ pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $
         run_passes(promoted_mir, Some(index));
 
         // Let's make sure we don't miss any nested instances
-        assert!(promoted_mir.promoted.is_empty());
+        debug_assert!(promoted_mir.promoted.is_empty());
     }
 }}
 
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 8a12a604ef202..6ec26eb5db5af 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -768,10 +768,10 @@ This does not pose a problem by itself because they can't be accessed directly."
 
             Rvalue::BinaryOp(op, ref lhs, _) => {
                 if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
-                    assert!(op == BinOp::Eq || op == BinOp::Ne ||
-                            op == BinOp::Le || op == BinOp::Lt ||
-                            op == BinOp::Ge || op == BinOp::Gt ||
-                            op == BinOp::Offset);
+                    debug_assert!(op == BinOp::Eq || op == BinOp::Ne ||
+                                  op == BinOp::Le || op == BinOp::Lt ||
+                                  op == BinOp::Ge || op == BinOp::Gt ||
+                                  op == BinOp::Offset);
 
                     self.add(Qualif::NOT_CONST);
                     if self.mode != Mode::Fn {
@@ -814,7 +814,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     if Some(def.did) == self.tcx.lang_items().unsafe_cell_type() {
                         let ty = rvalue.ty(self.mir, self.tcx);
                         self.add_type(ty);
-                        assert!(self.qualif.contains(Qualif::MUTABLE_INTERIOR));
+                        debug_assert!(self.qualif.contains(Qualif::MUTABLE_INTERIOR));
                     }
                 }
             }
@@ -836,7 +836,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                 match self.tcx.fn_sig(def_id).abi() {
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
-                        assert!(!self.tcx.is_const_fn(def_id));
+                        debug_assert!(!self.tcx.is_const_fn(def_id));
                         match &self.tcx.item_name(def_id).as_str()[..] {
                             | "size_of"
                             | "min_align_of"
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index da149f420644c..8fa3762a25164 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -122,7 +122,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         Some(args_and_span) => args_and_span,
         None => return,
     };
-    assert!(args.len() == 1);
+    debug_assert!(args.len() == 1);
     let peek_arg_place = match args[0] {
         mir::Operand::Copy(ref place @ mir::Place::Local(_)) |
         mir::Operand::Move(ref place @ mir::Place::Local(_)) => Some(place),
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index 7a8c35e7b96f5..d98d2d8fece72 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -82,9 +82,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
                     let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
                     if let ty::TyArray(item_ty, const_size) = place_ty.sty {
                         if let Some(size) = const_size.assert_usize(self.tcx) {
-                            assert!(size <= u32::max_value() as u64,
-                                    "uniform array move out doesn't supported
-                                     for array bigger then u32");
+                            debug_assert!(size <= u32::max_value() as u64,
+                                          "uniform array move out doesn't supported
+                                           for array bigger then u32");
                             self.uniform(location, dst_place, proj, item_ty, size as u32);
                         }
                     }
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
index c2a56adc18f5c..a4ddc4e1d85c4 100644
--- a/src/librustc_mir/util/patch.rs
+++ b/src/librustc_mir/util/patch.rs
@@ -48,7 +48,7 @@ impl<'tcx> MirPatch<'tcx> {
         for (bb, block) in mir.basic_blocks().iter_enumerated() {
             if let TerminatorKind::Resume = block.terminator().kind {
                 if block.statements.len() > 0 {
-                    assert!(resume_stmt_block.is_none());
+                    debug_assert!(resume_stmt_block.is_none());
                     resume_stmt_block = Some(bb);
                 } else {
                     resume_block = Some(bb);
@@ -119,7 +119,7 @@ impl<'tcx> MirPatch<'tcx> {
     }
 
     pub fn patch_terminator(&mut self, block: BasicBlock, new: TerminatorKind<'tcx>) {
-        assert!(self.patch_map[block].is_none());
+        debug_assert!(self.patch_map[block].is_none());
         debug!("MirPatch: patch_terminator({:?}, {:?})", block, new);
         self.patch_map[block] = Some(new);
     }
diff --git a/src/librustc_target/abi/call/mips64.rs b/src/librustc_target/abi/call/mips64.rs
index 3734e563d585e..50a8b4c162d2c 100644
--- a/src/librustc_target/abi/call/mips64.rs
+++ b/src/librustc_target/abi/call/mips64.rs
@@ -120,7 +120,7 @@ fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
                     if let abi::Float(abi::FloatTy::F64) = scalar.value {
                         if offset.is_abi_aligned(dl.f64_align) {
                             // Insert enough integers to cover [last_offset, offset)
-                            assert!(last_offset.is_abi_aligned(dl.f64_align));
+                            debug_assert!(last_offset.is_abi_aligned(dl.f64_align));
                             for _ in 0..((offset - last_offset).bits() / 64)
                                 .min((prefix.len() - prefix_index) as u64) {
 
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index dac4738e2b4bf..91c6cdd102204 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -620,7 +620,7 @@ impl Scalar {
         // However, that is fine here (it would still represent the full range),
         // i.e., if the range is everything.
         let bits = self.value.size(cx).bits();
-        assert!(bits <= 128);
+        debug_assert!(bits <= 128);
         let mask = !0u128 >> (128 - bits);
         let start = *self.valid_range.start();
         let end = *self.valid_range.end();
@@ -683,7 +683,7 @@ impl FieldPlacement {
             FieldPlacement::Union(_) => Size::ZERO,
             FieldPlacement::Array { stride, count } => {
                 let i = i as u64;
-                assert!(i < count);
+                debug_assert!(i < count);
                 stride * i
             }
             FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i]
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index c9b5fd525dd82..130181390d348 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -682,7 +682,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
 
             if is_if_let_fallback {
                 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
-                assert!(arm_ty.is_nil());
+                debug_assert!(arm_ty.is_nil());
                 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
             } else {
                 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index ec127d26ab307..fd87f774a3319 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -368,7 +368,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
 
         // we should not be invoked until the closure kind has been
         // determined by upvar inference
-        assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
+        debug_assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
 
         // We may now know enough to figure out fn vs fnmut etc.
         match fcx.try_overloaded_call_traits(self.call_expr,
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index f2745d06390e8..770063add4688 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -463,7 +463,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Create a `PolyFnSig`. Note the oddity that late bound
         // regions appearing free in `expected_sig` are now bound up
         // in this binder we are creating.
-        assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST));
+        debug_assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST));
         let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
             expected_sig.sig.inputs().iter().cloned(),
             expected_sig.sig.output(),
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index e3b0b8cccf31c..3e980504417a9 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1146,8 +1146,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
             // `expression_ty` will be unit).
             //
             // Another example is `break` with no argument expression.
-            assert!(expression_ty.is_nil());
-            assert!(expression_ty.is_nil(), "if let hack without unit type");
+            debug_assert!(expression_ty.is_nil(), "if let hack without unit type");
             fcx.at(cause, fcx.param_env)
                .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
                .map(|infer_ok| {
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index af4356dc8de78..1fcd576f2502e 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -80,7 +80,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
-        assert!(split.len() >= 2, "Atomic intrinsic not correct format");
+        debug_assert!(split.len() >= 2, "Atomic intrinsic not correct format");
 
         //We only care about the operation here
         let (n_tps, inputs, output) = match split[1] {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 6c3e265619fea..69d3af313f7fe 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -199,7 +199,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             // least during method dispach). This is because we
             // currently only unsize `[T;N]` to `[T]`, and naturally
             // that must occur being a reference.
-            assert!(pick.unsize.is_none());
+            debug_assert!(pick.unsize.is_none());
         }
 
         autoderef.finalize();
@@ -226,9 +226,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         match pick.kind {
             probe::InherentImplPick => {
                 let impl_def_id = pick.item.container.id();
-                assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(),
-                        "impl {:?} is not an inherent impl",
-                        impl_def_id);
+                debug_assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(),
+                              "impl {:?} is not an inherent impl",
+                              impl_def_id);
                 self.impl_self_ty(self.span, impl_def_id).substs
             }
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 04c32fa88271a..3cc7b01894fe0 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 value
             }
         };
-        assert!(!bounds.has_escaping_regions());
+        debug_assert!(!bounds.has_escaping_regions());
 
         let cause = traits::ObligationCause::misc(span, self.body_id);
         obligations.extend(traits::predicates_for_generics(cause.clone(),
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 8d8482208b97d..3dc6c7887f397 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -681,7 +681,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             // artifacts. This means it is safe to put into the
             // `WhereClauseCandidate` and (eventually) into the
             // `WhereClausePick`.
-            assert!(!trait_ref.substs.needs_infer());
+            debug_assert!(!trait_ref.substs.needs_infer());
 
             this.push_candidate(Candidate {
                 xform_self_ty, xform_ret_ty, item,
@@ -823,7 +823,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
     // THE ACTUAL SEARCH
 
     fn pick(mut self) -> PickResult<'tcx> {
-        assert!(self.method_name.is_some());
+        debug_assert!(self.method_name.is_some());
 
         if let Some(r) = self.pick_core() {
             return r;
@@ -863,7 +863,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                     .collect()
             }
             Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => {
-                assert!(others.is_empty());
+                debug_assert!(others.is_empty());
                 vec![]
             }
             _ => vec![],
@@ -1372,7 +1372,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                fn_sig,
                substs);
 
-        assert!(!substs.has_escaping_regions());
+        debug_assert!(!substs.has_escaping_regions());
 
         // It is possible for type parameters or early-bound lifetimes
         // to appear in the signature of `self`. The substitutions we
@@ -1487,7 +1487,7 @@ impl<'tcx> Candidate<'tcx> {
                     // inference variables or other artifacts. This
                     // means they are safe to put into the
                     // `WhereClausePick`.
-                    assert!(
+                    debug_assert!(
                         !trait_ref.skip_binder().substs.needs_infer()
                             && !trait_ref.skip_binder().substs.has_skol()
                     );
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4cde171f1bfd4..d22ecfbee5aa3 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -879,7 +879,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Closure and generater analysis may run after fallback
         // because they don't constrain other type variables.
         fcx.closure_analyze(body);
-        assert!(fcx.deferred_call_resolutions.borrow().is_empty());
+        debug_assert!(fcx.deferred_call_resolutions.borrow().is_empty());
         fcx.resolve_generator_interiors(def_id);
         fcx.select_all_obligations_or_error();
 
@@ -2168,7 +2168,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let mut anon_types = self.anon_types.borrow_mut();
         for (ty, decl) in anon_type_map {
             let old_value = anon_types.insert(ty, decl);
-            assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl);
+            debug_assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl);
         }
 
         value
@@ -2283,7 +2283,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                           cause: traits::ObligationCause<'tcx>,
                                           predicates: &ty::InstantiatedPredicates<'tcx>)
     {
-        assert!(!predicates.has_escaping_regions());
+        debug_assert!(!predicates.has_escaping_regions());
 
         debug!("add_obligations_for_parameters(predicates={:?})",
                predicates);
@@ -2332,7 +2332,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         use rustc::ty::error::UnconstrainedNumeric::Neither;
         use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
 
-        assert!(ty.is_ty_infer());
+        debug_assert!(ty.is_ty_infer());
         let fallback = match self.type_is_unconstrained_numeric(ty) {
             _ if self.is_tainted_by_errors() => self.tcx().types.err,
             UnconstrainedInt => self.tcx.types.i32,
@@ -2918,8 +2918,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // While we don't allow *arbitrary* coercions here, we *do* allow
         // coercions from ! to `expected`.
         if ty.is_never() {
-            assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id),
-                    "expression with never type wound up being adjusted");
+            debug_assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id),
+                          "expression with never type wound up being adjusted");
             let adj_ty = self.next_diverging_ty_var(
                 TypeVariableOrigin::AdjustmentType(expr.span));
             self.apply_adjustments(expr, vec![Adjustment {
@@ -3868,7 +3868,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         if let Some(ref e) = *expr_opt {
                             coerce.coerce(self, &cause, e, e_ty);
                         } else {
-                            assert!(e_ty.is_nil());
+                            debug_assert!(e_ty.is_nil());
                             coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
                         }
                     } else {
@@ -3879,7 +3879,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         // else an error would have been flagged by the
                         // `loops` pass for using break with an expression
                         // where you are not supposed to.
-                        assert!(expr_opt.is_none() || self.tcx.sess.err_count() > 0);
+                        debug_assert!(expr_opt.is_none() || self.tcx.sess.err_count() > 0);
                     }
 
                     ctxt.may_break = true;
@@ -4820,7 +4820,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //
         // The first step then is to categorize the segments appropriately.
 
-        assert!(!segments.is_empty());
+        debug_assert!(!segments.is_empty());
 
         let mut ufcs_associated = None;
         let mut type_segment = None;
@@ -5008,8 +5008,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // The things we are substituting into the type should not contain
         // escaping late-bound regions, and nor should the base type scheme.
         let ty = self.tcx.type_of(def.def_id());
-        assert!(!substs.has_escaping_regions());
-        assert!(!ty.has_escaping_regions());
+        debug_assert!(!substs.has_escaping_regions());
+        debug_assert!(!ty.has_escaping_regions());
 
         // Add all the obligations that are required, substituting and
         // normalized appropriately.
@@ -5298,7 +5298,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         } else if let ty::TyError = leaf_ty.sty {
             // If there is already another error, do not emit
             // an error for not using a type Parameter.
-            assert!(tcx.sess.err_count() > 0);
+            debug_assert!(tcx.sess.err_count() > 0);
             return;
         }
     }
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index cdf2b6ae44736..73ec19e1ca303 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -474,7 +474,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                            op: hir::UnOp)
                            -> Ty<'tcx>
     {
-        assert!(op.is_by_value());
+        debug_assert!(op.is_by_value());
         match self.lookup_op_method(operand_ty, &[], Op::Unary(op, ex.span)) {
             Ok(method) => {
                 self.write_method_call(ex.hir_id, method);
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 8aa5658d291db..c3d8983da9d45 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -130,7 +130,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
         rcx.resolve_regions_and_report_errors_unless_nll();
 
-        assert!(self.tables.borrow().free_region_map.is_empty());
+        debug_assert!(self.tables.borrow().free_region_map.is_empty());
         self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
     }
 
@@ -182,7 +182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // In this mode, we also copy the free-region-map into the
         // tables of the enclosing fcx. In the other regionck modes
         // (e.g., `regionck_item`), we don't have an enclosing tables.
-        assert!(self.tables.borrow().free_region_map.is_empty());
+        debug_assert!(self.tables.borrow().free_region_map.is_empty());
         self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
     }
 }
@@ -439,8 +439,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                 body_id: hir::BodyId,
                 span: Span,
                 id: ast::NodeId) {
-        assert!(match fk { intravisit::FnKind::Closure(..) => true, _ => false },
-                "visit_fn invoked for something other than a closure");
+        debug_assert!(match fk { intravisit::FnKind::Closure(..) => true, _ => false },
+                      "visit_fn invoked for something other than a closure");
 
         // Save state of current function before invoking
         // `visit_fn_body`.  We will restore afterwards.
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 61fe90be21774..885edd624b5a7 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -59,7 +59,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         InferBorrowKindVisitor { fcx: self }.visit_body(body);
 
         // it's our job to process these.
-        assert!(self.deferred_call_resolutions.borrow().is_empty());
+        debug_assert!(self.deferred_call_resolutions.borrow().is_empty());
     }
 }
 
@@ -447,7 +447,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
     fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind)
                               -> bool
     {
-        assert!(match borrow_kind {
+        debug_assert!(match borrow_kind {
             ty::MutBorrow => true,
             ty::UniqueImmBorrow => true,
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index b37f489b2c721..78a97ebc7f1df 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -108,7 +108,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) {
         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_skol());
+        debug_assert!(!ty.needs_infer() && !ty.has_skol());
         self.tables.node_types_mut().insert(hir_id, ty);
     }
 
@@ -539,7 +539,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) {
             let substs = self.resolve(&substs, &span);
             debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
-            assert!(!substs.needs_infer() && !substs.has_skol());
+            debug_assert!(!substs.needs_infer() && !substs.has_skol());
             self.tables.node_substs_mut().insert(hir_id, substs);
         }
     }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 4d9a4a03a6b50..3ee161651ba53 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -106,7 +106,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let span = tcx.hir.span(impl_node_id);
     let param_env = tcx.param_env(impl_did);
-    assert!(!self_type.has_escaping_regions());
+    debug_assert!(!self_type.has_escaping_regions());
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)",
            self_type);
@@ -200,7 +200,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
 
     let span = gcx.hir.span(impl_node_id);
     let param_env = gcx.param_env(impl_did);
-    assert!(!source.has_escaping_regions());
+    debug_assert!(!source.has_escaping_regions());
 
     let err_info = CoerceUnsizedInfo { custom_kind: None };
 
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 02a18fa47dff1..9b51c229cf98c 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -49,7 +49,7 @@ pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 ty_def_id: DefId)
                                 -> Lrc<Vec<DefId>> {
-    assert!(ty_def_id.is_local());
+    debug_assert!(ty_def_id.is_local());
 
     // NB. Until we adopt the red-green dep-tracking algorithm (see
     // [the plan] for details on that), we do some hackery here to get
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 0aec31609b060..e48563fd31bea 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -123,7 +123,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
         // Record the start of this item's inferreds.
         let start = self.inferred_terms.len();
         let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none();
-        assert!(newly_added);
+        debug_assert!(newly_added);
 
         // NB: In the code below for writing the results back into the
         // `CrateVariancesMap`, we rely on the fact that all inferreds
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index d42132440163c..ae6641d3805d7 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -1374,7 +1374,7 @@ impl Stack {
 
     // Used by Parser to remove the top-most element of the stack.
     fn pop(&mut self) {
-        assert!(!self.is_empty());
+        debug_assert!(!self.is_empty());
         match *self.stack.last().unwrap() {
             InternalKey(_, sz) => {
                 let new_size = self.str_buffer.len() - sz as usize;
diff --git a/src/libserialize/leb128.rs b/src/libserialize/leb128.rs
index ae7f25c7fedbe..bf9885eb8f286 100644
--- a/src/libserialize/leb128.rs
+++ b/src/libserialize/leb128.rs
@@ -75,7 +75,7 @@ macro_rules! impl_read_unsigned_leb128 {
             }
 
             // Do a single bounds check at the end instead of for every byte.
-            assert!(position <= slice.len());
+            debug_assert!(position <= slice.len());
 
             (result, position)
         }
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 137b94230a3cd..2210d8717665d 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -416,7 +416,7 @@ pub fn mk_attr_id() -> AttrId {
     static NEXT_ATTR_ID: AtomicUsize = AtomicUsize::new(0);
 
     let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
-    assert!(id != ::std::usize::MAX);
+    debug_assert!(id != ::std::usize::MAX);
     AttrId(id)
 }
 
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 0a9991d33b186..38823fcea6655 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -354,7 +354,7 @@ impl CodeMap {
                 debug!("char pos {:?} is on the line at char pos {:?}",
                        chpos, linechpos);
                 debug!("byte is on line: {}", line);
-                assert!(chpos >= linechpos);
+                debug_assert!(chpos >= linechpos);
                 Loc {
                     file: f,
                     line,
@@ -490,7 +490,7 @@ impl CodeMap {
                 end: (hi.file.name.clone(), hi.file.start_pos),
             }));
         }
-        assert!(hi.line >= lo.line);
+        debug_assert!(hi.line >= lo.line);
 
         let mut lines = Vec::with_capacity(hi.line - lo.line + 1);
 
@@ -831,13 +831,13 @@ impl CodeMap {
                 total_extra_bytes += mbc.bytes as u32 - 1;
                 // We should never see a byte position in the middle of a
                 // character
-                assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
+                debug_assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
             } else {
                 break;
             }
         }
 
-        assert!(map.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32());
+        debug_assert!(map.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32());
         CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize)
     }
 
@@ -859,7 +859,8 @@ impl CodeMap {
             }
         }
 
-        assert!(a < count, "position {} does not resolve to a source location", pos.to_usize());
+        debug_assert!(a < count, "position {} does not resolve to a source location",
+            pos.to_usize());
 
         return a;
     }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 3046525b7144c..c0a060da75777 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -653,7 +653,7 @@ pub fn parse(
 
         // Matcher positions that would be valid if the macro invocation was over now
         let mut eof_items = SmallVector::new();
-        assert!(next_items.is_empty());
+        debug_assert!(next_items.is_empty());
 
         // Process `cur_items` until either we have finished the input or we need to get some
         // parsing from the black-box parser done. The result is that `next_items` will contain a
@@ -673,7 +673,7 @@ pub fn parse(
         }
 
         // inner parse loop handled all cur_items, so it's empty
-        assert!(cur_items.is_empty());
+        debug_assert!(cur_items.is_empty());
 
         // We need to do some post processing after the `inner_parser_loop`.
         //
@@ -757,7 +757,7 @@ pub fn parse(
             cur_items.push(item);
         }
 
-        assert!(!cur_items.is_empty());
+        debug_assert!(!cur_items.is_empty());
     }
 }
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index c9ec2c7d1e86a..c3915b6b2df5d 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -503,7 +503,7 @@ impl FirstSets {
 
         let mut first = TokenSet::empty();
         for tt in tts.iter() {
-            assert!(first.maybe_empty);
+            debug_assert!(first.maybe_empty);
             match *tt {
                 TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
                     first.add_one(tt.clone());
@@ -525,7 +525,7 @@ impl FirstSets {
                                 first.add_one_maybe(TokenTree::Token(sp, sep.clone()));
                             }
 
-                            assert!(first.maybe_empty);
+                            debug_assert!(first.maybe_empty);
                             first.add_all(subfirst);
                             if subfirst.maybe_empty ||
                                seq_rep.op == quoted::KleeneOp::ZeroOrMore {
@@ -553,7 +553,7 @@ impl FirstSets {
 
         // we only exit the loop if `tts` was empty or if every
         // element of `tts` matches the empty sequence.
-        assert!(first.maybe_empty);
+        debug_assert!(first.maybe_empty);
         first
     }
 }
diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs
index 20a585b6601a5..8a4b7e1c4f56e 100644
--- a/src/libsyntax/parse/lexer/comments.rs
+++ b/src/libsyntax/parse/lexer/comments.rs
@@ -46,7 +46,7 @@ fn is_doc_comment(s: &str) -> bool {
 }
 
 pub fn doc_comment_style(comment: &str) -> ast::AttrStyle {
-    assert!(is_doc_comment(comment));
+    debug_assert!(is_doc_comment(comment));
     if comment.starts_with("//!") || comment.starts_with("/*!") {
         ast::AttrStyle::Inner
     } else {
@@ -242,7 +242,7 @@ fn read_block_comment(rdr: &mut StringReader,
     // Count the number of chars since the start of the line by rescanning.
     let mut src_index = rdr.src_index(rdr.filemap.line_begin_pos(rdr.pos));
     let end_src_index = rdr.src_index(rdr.pos);
-    assert!(src_index <= end_src_index,
+    debug_assert!(src_index <= end_src_index,
         "src_index={}, end_src_index={}, line_begin_pos={}",
         src_index, end_src_index, rdr.filemap.line_begin_pos(rdr.pos).to_u32());
     let mut n = 0;
@@ -272,7 +272,7 @@ fn read_block_comment(rdr: &mut StringReader,
         if is_block_doc_comment(&curr_line[..]) {
             return;
         }
-        assert!(!curr_line.contains('\n'));
+        debug_assert!(!curr_line.contains('\n'));
         lines.push(curr_line);
     } else {
         let mut level: isize = 1;
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index f9b9e95ead1b6..db976c045f645 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -122,7 +122,7 @@ impl<'a> StringReader<'a> {
     }
     /// Return the next token. EFFECT: advances the string_reader.
     pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
-        assert!(self.fatal_errs.is_empty());
+        debug_assert!(self.fatal_errs.is_empty());
         let ret_val = TokenAndSpan {
             tok: replace(&mut self.peek_tok, token::Whitespace),
             sp: self.peek_span,
@@ -707,7 +707,7 @@ impl<'a> StringReader<'a> {
     /// interested in, and errors will be emitted for any digits
     /// between `real_radix` and `scan_radix`.
     fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
-        assert!(real_radix <= scan_radix);
+        debug_assert!(real_radix <= scan_radix);
         let mut len = 0;
         loop {
             let c = self.ch;
@@ -1580,8 +1580,8 @@ impl<'a> StringReader<'a> {
 
     fn read_one_line_comment(&mut self) -> String {
         let val = self.read_to_eol();
-        assert!((val.as_bytes()[0] == b'/' && val.as_bytes()[1] == b'/') ||
-                (val.as_bytes()[0] == b'#' && val.as_bytes()[1] == b'!'));
+        debug_assert!((val.as_bytes()[0] == b'/' && val.as_bytes()[1] == b'/') ||
+                      (val.as_bytes()[0] == b'#' && val.as_bytes()[1] == b'!'));
         val
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index d029509f0c12d..df77c2e71d9e2 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -897,9 +897,9 @@ mod tests {
             for &src in &srcs {
                 let spans = get_spans_of_pat_idents(src);
                 let (lo, hi) = (spans[0].lo(), spans[0].hi());
-                assert!("self" == &src[lo.to_usize()..hi.to_usize()],
-                        "\"{}\" != \"self\". src=\"{}\"",
-                        &src[lo.to_usize()..hi.to_usize()], src)
+                debug_assert!("self" == &src[lo.to_usize()..hi.to_usize()],
+                              "\"{}\" != \"self\". src=\"{}\"",
+                              &src[lo.to_usize()..hi.to_usize()], src)
             }
         })
     }
@@ -990,7 +990,7 @@ mod tests {
             ).unwrap().unwrap();
 
             if let ast::ItemKind::Mod(ref m) = item.node {
-                assert!(m.items.len() == 2);
+                debug_assert!(m.items.len() == 2);
             } else {
                 panic!();
             }
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 086de35d531c7..64053dd6fc26a 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -543,7 +543,7 @@ impl<'a> Printer<'a> {
           Token::End => {
             debug!("print End -> pop End");
             let print_stack = &mut self.print_stack;
-            assert!(!print_stack.is_empty());
+            debug_assert!(!print_stack.is_empty());
             print_stack.pop().unwrap();
             Ok(())
           }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index e0f985c26c7a1..1ee3a1cf41bbd 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -1296,7 +1296,7 @@ impl<'a> MethodDef<'a> {
                             // opt_idents are the same.  (Assert
                             // here to make it self-evident that
                             // it is okay to ignore `_opt_ident`.)
-                            assert!(opt_ident == _opt_ident);
+                            debug_assert!(opt_ident == _opt_ident);
 
                             other_getter_expr.clone()
                         }).collect::<Vec<P<Expr>>>();
diff --git a/src/libsyntax_pos/analyze_filemap.rs b/src/libsyntax_pos/analyze_filemap.rs
index c7c0263e45932..6d65fe91c7e16 100644
--- a/src/libsyntax_pos/analyze_filemap.rs
+++ b/src/libsyntax_pos/analyze_filemap.rs
@@ -37,7 +37,7 @@ pub fn analyze_filemap(
     // it again.
     if let Some(&last_line_start) = lines.last() {
         let file_map_end = filemap_start_pos + BytePos::from_usize(src.len());
-        assert!(file_map_end >= last_line_start);
+        debug_assert!(file_map_end >= last_line_start);
         if last_line_start == file_map_end {
             lines.pop();
         }
@@ -114,7 +114,7 @@ cfg_if! {
 
                 // If the bit mask is all zero, we only have ASCII chars here:
                 if multibyte_mask == 0 {
-                    assert!(intra_chunk_offset == 0);
+                    debug_assert!(intra_chunk_offset == 0);
 
                     // Check if there are any control characters in the chunk. All
                     // control characters that we can encounter at this point have a
@@ -219,7 +219,7 @@ fn analyze_filemap_generic(src: &str,
                            non_narrow_chars: &mut Vec<NonNarrowChar>)
                            -> usize
 {
-    assert!(src.len() >= scan_len);
+    debug_assert!(src.len() >= scan_len);
     let mut i = 0;
     let src_bytes = src.as_bytes();
 
@@ -260,7 +260,7 @@ fn analyze_filemap_generic(src: &str,
             let pos = BytePos::from_usize(i) + output_offset;
 
             if char_len > 1 {
-                assert!(char_len >=2 && char_len <= 4);
+                debug_assert!(char_len >=2 && char_len <= 4);
                 let mbc = MultiByteChar {
                     pos,
                     bytes: char_len as u8,
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 44cd53282ec9f..532f9a21d22dc 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -123,7 +123,7 @@ impl std::fmt::Display for FileName {
 
 impl From<PathBuf> for FileName {
     fn from(p: PathBuf) -> Self {
-        assert!(!p.to_string_lossy().ends_with('>'));
+        debug_assert!(!p.to_string_lossy().ends_with('>'));
         FileName::Real(p)
     }
 }
@@ -1089,7 +1089,7 @@ impl FileMap {
         }
 
         let line_index = lookup_line(&self.lines[..], pos);
-        assert!(line_index < self.lines.len() as isize);
+        debug_assert!(line_index < self.lines.len() as isize);
         if line_index >= 0 {
             Some(line_index as usize)
         } else {
@@ -1102,7 +1102,7 @@ impl FileMap {
             return (self.start_pos, self.end_pos);
         }
 
-        assert!(line_index < self.lines.len());
+        debug_assert!(line_index < self.lines.len());
         if line_index == (self.lines.len() - 1) {
             (self.lines[line_index], self.end_pos)
         } else {