diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index ae13275e4b35d..378a53585af0e 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -631,8 +631,27 @@ impl OsStr {
         s.as_ref()
     }
 
+    /// Creates a new [`OsStr`] from a [`str`].
+    ///
+    /// This method supports const expressions. However, if you don't need const,
+    /// you should probably use the [`OsStr::new`] method instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(const_path)]
+    /// use std::ffi::OsStr;
+    ///
+    /// const OS_STR: &OsStr = OsStr::from_str("foo");
+    /// ```
+    #[inline]
+    #[unstable(feature = "const_path", reason = "TBD", issue = "none")]
+    pub const fn from_str(s: &str) -> &OsStr {
+        Self::from_inner(Slice::from_str(s))
+    }
+
     #[inline]
-    fn from_inner(inner: &Slice) -> &OsStr {
+    const fn from_inner(inner: &Slice) -> &OsStr {
         // SAFETY: OsStr is just a wrapper of Slice,
         // therefore converting &Slice to &OsStr is safe.
         unsafe { &*(inner as *const Slice as *const OsStr) }
@@ -1263,7 +1282,7 @@ impl AsRef<OsStr> for OsString {
 impl AsRef<OsStr> for str {
     #[inline]
     fn as_ref(&self) -> &OsStr {
-        OsStr::from_inner(Slice::from_str(self))
+        OsStr::from_str(self)
     }
 }
 
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index 283f2b577e896..6b00ae98a3bb9 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -163,3 +163,10 @@ fn into_rc() {
     assert_eq!(&*rc2, os_str);
     assert_eq!(&*arc2, os_str);
 }
+
+#[test]
+pub fn test_const() {
+    const STR: &str = "/foo/bar";
+    const OS_STR: &OsStr = OsStr::from_str(STR);
+    assert_eq!(OS_STR, OsStr::new(STR));
+}
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 36d6469c02d31..9a8fcb8828669 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1973,7 +1973,27 @@ impl Path {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
-        unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
+        Self::from_os_str(s.as_ref())
+    }
+
+    /// Creates a new [`Path`] from an [`OsStr`].
+    ///
+    /// This method supports const expressions. However, if you don't need const,
+    /// you should probably use the [`Path::new`] method instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(const_path)]
+    /// use std::ffi::OsStr;
+    /// use std::path::Path;
+    ///
+    /// const PATH: &Path = Path::from_os_str(OsStr::from_str("/foo/bar"));
+    /// ```
+    #[inline]
+    #[unstable(feature = "const_path", reason = "TBD", issue = "none")]
+    pub const fn from_os_str(s: &OsStr) -> &Path {
+        unsafe { &*(s as *const OsStr as *const Path) }
     }
 
     /// Yields the underlying [`OsStr`] slice.
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index 351cf698810f1..5140e0f932fc6 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -1701,6 +1701,13 @@ fn test_ord() {
     ord!(Equal, "foo/bar", "foo/bar//");
 }
 
+#[test]
+pub fn test_const() {
+    const STR: &str = "/foo/bar";
+    const PATH: &Path = Path::from_os_str(OsStr::from_str(STR));
+    assert_eq!(PATH, Path::new(STR));
+}
+
 #[test]
 #[cfg(unix)]
 fn test_unix_absolute() {
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index ccbc182240cf3..b56c53f802108 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -186,12 +186,12 @@ impl Buf {
 
 impl Slice {
     #[inline]
-    fn from_u8_slice(s: &[u8]) -> &Slice {
+    const fn from_u8_slice(s: &[u8]) -> &Slice {
         unsafe { mem::transmute(s) }
     }
 
     #[inline]
-    pub fn from_str(s: &str) -> &Slice {
+    pub const fn from_str(s: &str) -> &Slice {
         Slice::from_u8_slice(s.as_bytes())
     }
 
diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs
index 11883f15022f6..0f6f63f0bd4de 100644
--- a/library/std/src/sys/windows/os_str.rs
+++ b/library/std/src/sys/windows/os_str.rs
@@ -151,7 +151,7 @@ impl Buf {
 
 impl Slice {
     #[inline]
-    pub fn from_str(s: &str) -> &Slice {
+    pub const fn from_str(s: &str) -> &Slice {
         unsafe { mem::transmute(Wtf8::from_str(s)) }
     }
 
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 57fa4989358a4..bd4312063f37b 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -507,7 +507,7 @@ impl Wtf8 {
     ///
     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
     #[inline]
-    pub fn from_str(value: &str) -> &Wtf8 {
+    pub const fn from_str(value: &str) -> &Wtf8 {
         unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
     }
 
@@ -516,7 +516,7 @@ impl Wtf8 {
     /// Since the byte slice is not checked for valid WTF-8, this functions is
     /// marked unsafe.
     #[inline]
-    unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
+    const unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
         mem::transmute(value)
     }